第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定

Dubbo原理剖析資料詳解

標(biāo)簽:
Java 架構(gòu) 中間件
概述

本文深入剖析了Dubbo的原理,介绍了其作为高性能Java RPC框架的核心功能与优势,包括服务注册与发现、服务治理等机制。文章详细讲解了Dubbo的基本概念、架构设计以及服务提供者和消费者的配置与启动流程,提供了丰富的配置示例和代码演示。此外,还探讨了Dubbo的路由与负载均衡机制及其在实际应用中的优化技巧。从基础概念到高级配置,Dubbo原理剖析资料涵盖了全方位的内容。

Dubbo概述

Dubbo 是一个高性能、开源的 Java RPC 框架。它允许开发者通过简单的 API 和配置来实现服务的远程调用。Dubbo 旨在提供一种轻量级的、高性能的服务治理体系,为微服务架构提供了强有力的支持。

Dubbo是什么

Dubbo 是阿里巴巴开源的一款分布式服务框架,它使得开发者可以更方便地调用远程服务。Dubbo 的设计目标是为了解决大规模分布式系统中的服务治理问题,提供高效的服务调用和管理能力。

Dubbo的作用与优势

Dubbo 的主要作用是帮助开发人员搭建一个分布式服务的框架,使得服务的调用、服务的治理、服务的监控变得更加简单可行。其优势包括:

  • 高性能:Dubbo 使用 Netty 作为网络通讯框架,提供了高效的网络通信能力。
  • 服务治理:Dubbo 提供了服务注册与发现机制,使得服务的动态治理变得简单。
  • 扩展性:Dubbo 的插件机制允许开发者扩展或替换框架中的任何组件。
  • 社区活跃:Dubbo 作为一款成熟的开源框架,拥有广泛的用户基础和活跃的社区支持。
Dubbo的基本概念和架构

Dubbo 的架构设计主要由以下组件构成:

  • 注册中心:Dubbo 支持多种注册中心,如 Zookeeper, Eureka, Consul 等,用于服务注册与发现。
  • 服务提供者:服务提供者将服务注册到注册中心,并实现服务的提供。
  • 服务消费者:服务消费者从注册中心获取服务提供者的地址信息,并调用服务。
  • 服务接口:服务提供者和消费者之间进行服务调用时定义的接口。
  • 配置中心:用于统一管理配置信息,如服务配置、环境配置等。
  • 监控中心:用于收集和展示服务调用的统计信息,如服务调用次数、请求时延等。
  • 集群管理:管理服务提供者的集群,支持负载均衡、故障转移等功能。
Dubbo的服务提供者

服务提供者是 Dubbo 架构中的一个重要组成部分,负责提供实际的服务。服务提供者的配置与启动流程是实现服务调用的基础。

服务提供者的配置

服务提供者的配置通常包含以下几部分内容:

  • 服务接口:需要提供给消费者调用的服务接口。
  • 服务实现:服务的具体实现类。
  • 服务配置:包括服务名、版本、协议类型等。

以下是一个简单的服务提供者的配置示例:

<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>

<bean id="demoService" class="com.demo.DemoServiceImpl"/>
<dubbo:service interface="com.demo.DemoService" ref="demoService"/>

使用 Java 配置类进行配置的示例:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.DubboBootstrap;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-provider");

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 启动服务
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
                .registry(registryConfig)
                .protocol(protocolConfig)
                .run();

        System.out.println("Provider started.");
    }
}
服务提供者的启动流程

服务提供者的启动流程通常包括以下几个步骤:

  1. 加载配置:加载服务提供者的配置信息,包括服务接口、服务实现、服务配置等。
  2. 注册服务:将服务注册到注册中心,供服务消费者发现。
  3. 启动服务:启动服务提供者的服务框架,监听服务调用请求。

以下是一个服务提供者的启动流程示例代码:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.DubboBootstrap;
import com.alibaba.dubbo.registry.RegistryService;
import com.alibaba.dubbo.rpc.service.GenericService;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-provider");

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 注册服务
        GenericService genericService = (GenericService) DubboBootstrap.getExtension(RegistryService.class).refer(GenericService.class, registryConfig);

        // 启动服务
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
                .registry(registryConfig)
                .protocol(protocolConfig)
                .run();

        System.out.println("Provider started.");
    }
}
如何编写服务提供者代码

服务提供者的代码主要包括服务接口定义和实现类的编写。以下是一个简单的服务提供者代码示例:

// 服务接口定义
public interface DemoService {
    String sayHello(String name);
}

// 服务实现类
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}
Dubbo的服务消费者

服务消费者是 Dubbo 架构中的另一个重要组成部分,它通过注册中心获取服务提供者的地址信息,并调用服务。

服务消费者的配置

服务消费者的配置通常包含以下几部分内容:

  • 服务接口:需要调用的服务接口。
  • 服务配置:包括服务名、版本、协议类型等。

以下是一个简单的服务消费者的配置示例:

<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" interface="com.demo.DemoService"/>

使用 Java 配置类进行配置的示例:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-consumer");

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setApplication(applicationConfig);
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();

        // 调用服务
        String result = demoService.sayHello("world");
        System.out.println("Result: " + result);

        System.out.println("Consumer started.");
    }
}
服务消费者的启动流程

服务消费者的启动流程通常包括以下几个步骤:

  1. 加载配置:加载服务消费者的服务接口和配置信息。
  2. 注册服务:将服务消费者的信息注册到注册中心。
  3. 发现服务提供者:从注册中心获取服务提供者的地址信息。
  4. 调用服务:通过获取到的服务提供者的地址信息,调用服务。

以下是一个服务消费者的启动流程示例代码:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-consumer");

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setApplication(applicationConfig);
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();

        // 调用服务
        String result = demoService.sayHello("world");
        System.out.println("Result: " + result);

        System.out.println("Consumer started.");
    }
}
如何编写服务消费者代码

服务消费者的服务接口调用代码如下:

public interface DemoService {
    String sayHello(String name);
}

服务消费者的主程序代码如下:

public class ConsumerApplication {

    public static void main(String[] args) {
        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setApplication(new ApplicationConfig("demo-consumer"));
        referenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();

        // 调用服务
        String result = demoService.sayHello("world");
        System.out.println("Result: " + result);
    }
}
Dubbo的核心组件详解

Dubbo 的核心组件主要包括注册中心、服务提供者与服务消费者交互过程、路由与负载均衡机制。

注册中心

注册中心是 Dubbo 服务治理的核心组件之一,它负责服务的注册与发现。Dubbo 支持多种注册中心,如 Zookeeper, Eureka, Consul 等。

注册中心的作用

注册中心的主要作用包括:

  • 服务注册:服务提供者将服务注册到注册中心,注册信息包括服务名、版本号、IP 地址、端口号等。
  • 服务发现:服务消费者从注册中心获取服务提供者的地址信息,实现服务调用。
  • 服务变更:服务提供者在服务变更时(如服务重启、服务升级等),将变更信息通知注册中心,注册中心同步变更信息到其他服务消费者。

注册中心的工作流程

注册中心的工作流程包括以下几个步骤:

  1. 服务注册:服务提供者将服务信息注册到注册中心。
  2. 服务发现:服务消费者从注册中心获取服务提供者的地址信息。
  3. 服务变更通知:服务提供者在服务变更时,将变更信息通知注册中心,注册中心同步变更信息到其他服务消费者。

配置注册中心

以下是一个注册中心的配置示例:

<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
服务提供者与服务消费者交互过程

服务提供者与服务消费者之间的交互过程包括服务注册、服务发现、服务调用等。

服务注册与发现

服务注册与发现是服务提供者和消费者之间的基本交互过程。服务提供者将服务注册到注册中心,服务消费者从注册中心获取服务提供者的地址信息。

服务调用

服务调用是指消费者根据服务提供者的地址信息调用服务的过程。Dubbo 支持多种服务调用协议,如 Dubbo, HTTP, Thrift 等。

配置服务提供者与消费者

以下是一个服务提供者和服务消费者的基本配置示例:

<!-- 服务提供者配置 -->
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>

<bean id="demoService" class="com.demo.DemoServiceImpl"/>
<dubbo:service interface="com.demo.DemoService" ref="demoService"/>

<!-- 服务消费者配置 -->
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" interface="com.demo.DemoService"/>
路由与负载均衡机制

路由与负载均衡是 Dubbo 服务治理的重要机制,用于实现服务的高可用性和性能优化。

路由机制

路由机制是指服务消费者从多个服务提供者中选择合适的服务提供者进行服务调用。Dubbo 支持多种路由策略,如路由规则、路由组等。

负载均衡机制

负载均衡机制是指服务消费者从多个服务提供者中选择合适的服务提供者进行服务调用。Dubbo 支持多种负载均衡策略,如轮询、随机、最少连接数等。

配置路由与负载均衡

以下是一个路由与负载均衡的配置示例:

<!-- 路由配置 -->
<dubbo:route id="route1" condition="ip==192.168.1.1">
    <dubbo:rule priority="1"/>
</dubbo:route>

<!-- 负载均衡配置 -->
<dubbo:protocol name="dubbo" port="20880" loadbalance="roundrobin"/>
示例代码展示

以下是一个具体的负载均衡配置示例,展示了如何使用轮询策略进行负载均衡:

<dubbo:protocol name="dubbo" port="20880" loadbalance="roundrobin"/>
注册中心的实现细节

注册中心的具体实现细节包括以下几个方面:

  • 服务注册:服务提供者将服务信息注册到注册中心。
  • 服务发现:服务消费者从注册中心获取服务提供者的地址信息。
  • 服务变更:服务提供者在服务变更时,将变更信息通知注册中心,注册中心同步变更信息到其他服务消费者。

服务注册的实现

服务提供者将服务信息注册到注册中心的具体实现如下:

import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.registry.RegistryService;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 注册服务
        RegistryService registryService = (RegistryService) DubboBootstrap.getExtension(RegistryService.class).refer(RegistryService.class, registryConfig);
        registryService.register("demo-service", "127.0.0.1:20880");
    }
}

服务发现的实现

服务消费者从注册中心获取服务提供者的地址信息的具体实现如下:

import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();
        String address = demoService.getUrl();
        System.out.println("Service Address: " + address);
    }
}

服务变更通知的实现

服务提供者在服务变更时,将变更信息通知注册中心的具体实现如下:

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 注册服务
        RegistryService registryService = (RegistryService) DubboBootstrap.getExtension(RegistryService.class).refer(RegistryService.class, registryConfig);
        registryService.register("demo-service", "127.0.0.1:20880");

        // 服务变更通知
        registryService.update("demo-service", "127.0.0.1:20881");
    }
}
服务提供者与服务消费者交互的实现细节

服务提供者与服务消费者之间的交互过程包括服务注册、服务发现和服务调用。具体实现如下:

服务注册的实现

import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.registry.RegistryService;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 注册服务
        RegistryService registryService = (RegistryService) DubboBootstrap.getExtension(RegistryService.class).refer(RegistryService.class, registryConfig);
        registryService.register("demo-service", "127.0.0.1:20880");
    }
}

服务发现的实现

import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();
        String address = demoService.getUrl();
        System.out.println("Service Address: " + address);
    }
}

服务调用的实现

import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();

        // 调用服务
        String result = demoService.sayHello("world");
        System.out.println("Result: " + result);
    }
}
Dubbo的配置管理

Dubbo 的配置管理包括如何配置 Dubbo 服务、配置文件详解、环境变量与系统属性的应用等。

如何配置Dubbo服务

Dubbo 服务的配置可以通过 XML 配置文件或 Java 配置类来完成。以下是一个通过 XML 配置文件进行服务配置的示例:

<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>

<bean id="demoService" class="com.demo.DemoServiceImpl"/>
<dubbo:service interface="com.demo.DemoService" ref="demoService"/>

使用 Java 配置类进行配置的示例:

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.DubboBootstrap;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-provider");

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 启动服务
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
                .registry(registryConfig)
                .protocol(protocolConfig)
                .run();

        System.out.println("Provider started.");
    }
}
配置文件详解

Dubbo 的配置文件通常包含以下几个部分:

  • Application:定义应用的基本信息,如应用名、版本号等。
  • Registry:定义注册中心的信息,如注册中心类型、地址等。
  • Protocol:定义服务协议的信息,如协议类型、端口号等。
  • Service:定义服务的配置信息,如服务接口、服务实现等。

Application 配置

<dubbo:application name="demo-provider"/>

Registry 配置

<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

Protocol 配置

<dubbo:protocol name="dubbo" port="20880"/>

Service 配置

<bean id="demoService" class="com.demo.DemoServiceImpl"/>
<dubbo:service interface="com.demo.DemoService" ref="demoService"/>
环境变量与系统属性的应用

环境变量与系统属性可以用于配置 Dubbo 服务,例如通过环境变量设置注册中心地址:

export DUBBO_REGISTRY_ADDRESS=zookeeper://127.0.0.1:2181

或者通过系统属性设置应用名:

System.setProperty("dubbo.application.name", "demo-provider");
Dubbo常见问题与解决方案

在使用 Dubbo 过程中,可能会遇到一些常见问题,以下是一些常见的错误及其解决方法、性能优化技巧及典型案例分析与实践。

常见错误及其解决方法

常见错误

  1. 服务未启动:服务提供者未启动,导致服务消费者调用失败。
  2. 服务未注册:服务提供者未注册到注册中心,导致服务消费者找不到服务提供者。
  3. 网络问题:网络不通或注册中心不可达,导致服务调用失败。

解决方法

  1. 服务未启动:确保服务提供者的启动代码正确无误,检查服务提供者的日志输出。
  2. 服务未注册:检查服务提供者的注册配置是否正确,确保注册中心能接收到注册信息。
  3. 网络问题:检查网络配置,确保网络通畅,注册中心地址正确。
性能优化技巧

性能优化

  1. 优化服务接口:减少接口参数,优化接口设计。
  2. 优化服务实现:减少服务实现中的耗时操作,提高服务实现的性能。
  3. 优化网络通信:使用高性能的网络通信框架,如 Netty。

配置优化

  1. 压缩通信数据:使用序列化框架进行数据压缩,如 Hessian、FST。
  2. 负载均衡:合理配置负载均衡策略,提高服务调用的性能。
  3. 连接池:使用连接池管理服务提供者的连接,减少连接建立的开销。
典型案例分析与实践

案例分析

假设有一个电商平台,需要实现商品信息的远程调用。服务提供者负责提供商品信息查询服务,服务消费者负责调用该服务并显示商品信息。

案例代码

服务提供者代码

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.DubboBootstrap;

public class ProviderApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-provider");

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 启动服务
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(applicationConfig)
                .registry(registryConfig)
                .protocol(protocolConfig)
                .run();

        System.out.println("Provider started.");
    }
}

服务消费者代码

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;

public class ConsumerApplication {

    public static void main(String[] args) {
        // 配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("demo-consumer");

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");

        // 创建服务引用
        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setApplication(applicationConfig);
        referenceConfig.setRegistry(registryConfig);
        referenceConfig.setInterface(DemoService.class);

        // 获取服务实例
        DemoService demoService = referenceConfig.get();

        // 调用服务
        String result = demoService.sayHello("world");
        System.out.println("Result: " + result);

        System.out.println("Consumer started.");
    }
}

服务接口代码

public interface DemoService {
    String sayHello(String name);
}

服务实现代码

public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

通过上述案例的分析与实践,可以更好地理解 Dubbo 的使用方法和配置技巧,从而提升服务调用的性能和可靠性。

點擊查看更多內(nèi)容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊有機(jī)會得

100積分直接送

付費專欄免費學(xué)

大額優(yōu)惠券免費領(lǐng)

立即參與 放棄機(jī)會
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號

舉報

0/150
提交
取消