乐趣区

关于java:分布式服务治理框架Dubbo的前世今生及应用实战

Dubbo 的呈现背景

Dubbo 从开源到当初,曾经呈现了靠近 10 年工夫,在国内各大企业被广泛应用。它到底有什么魔力值得大家去追捧呢?本篇文章给大家做一个具体的阐明。

大规模服务化对于服务治理的要求

当企业开始大规模的服务化当前,近程通信带来的弊病就越来越显著了。比如说

  1. 服务链路变长了,如何实现对服务链路的跟踪和监控呢?
  2. 服务的大规模集群使得服务之间须要依赖第三方注册核心来解决服务的发现和服务的感知问题
  3. 服务通信之间的异样,须要有一种爱护机制避免一个节点故障引发大规模的系统故障,所以要有容错机制
  4. 服务大规模集群会是的客户端须要引入负载平衡机制实现申请散发

而这些对于服务治理的要求,传统的 RPC 技术在这样的场景中显得有点力不从心,因而很多企业开始研发本人的 RPC 框架,比方阿里的 HSF、Dubbo;京东的 JSF 框架、当当的 dubbox、新浪的 motan、蚂蚁金服的 sofa 等等

有技术输入能力的公司,都会研发适宜本人场景的 rpc 框架,要么是从 0 到 1 开发,要么是基于现有的思维联合公司业务特色进行革新。而没有技术输入能力的公司,遇到服务治理的需要时,会优先选择那些比拟成熟的开源框架。而 Dubbo 就是其中一个

dubbo 次要是一个分布式服务治理解决方案,那么什么是服务治理?服务治理次要是针对大规模服务化当前,服务之间的路由、负载平衡、容错机制、服务降级这些问题的解决方案,而 Dubbo 实现的不仅仅是近程服务通信,并且还解决了服务路由、负载、降级、容错等性能。

Dubbo 的倒退历史

Dubbo 是阿里巴巴外部应用的一个分布式服务治理框架,2012 年开源,因为 Dubbo 在公司外部通过了很多的验证相对来说比拟成熟,所以在很短的的还是件就被很多互联网公司应用,再加上阿里进去的很多技术大牛进入各个守业公司负责技术架构当前,都以 Dubbo 作为主推的 RPC 框架使得 dubbo 很快成为了很多互联网公司的首要抉择。并且很多公司在利用 dubbo 时,会基于本身业务个性进行优化和改良,所以也衍生了很多版本,比方京东的 JSF、比方新浪的 Motan、比方当当的 dubbox.

在 2014 年 10 月份,Dubbo 进行了保护。起初在 2017 年的 9 月份,阿里发表重启 Dubbo,并且对于 Dubbo 做好了长期投入的筹备,并且在这段时间 Dubbo 进行了十分多的更新,目前的版本曾经到了 2.7.

2018 年 1 月 8 日,Dubbo 创始人之一梁飞在 Dubbo 交换群里走漏了 Dubbo 3.0 正在动工的音讯。Dubbo 3.0 内核与 Dubbo2.0 齐全不同,但兼容 Dubbo 2.0。Dubbo 3.0 将反对可选 Service Mesh

2018 年 2 月份,Dubbo 捐给了 Apache。另外,阿里巴巴对于 Spring Cloud Alibaba 生态的欠缺,以及 Spring Cloud 团队对于 alibaba 整个服务治理生态的反对,所以 Dubbo 将来仍然是国内绝大部分公司的首要抉择。

Dubbo 的整体架构

Dubbo 的应用

首先,构建两个 maven 我的项目

  • user-service

    • user-service-api
    • user-service-provider
  • user-service-consumer

user-service-api

user-service 提供服务的公共契约,外面提供了 user-service 对外的服务。

public interface ILoginService {String login(String username,String password);
}

user-service-provider

在 user-service-provider 服务中,提供 ILoginService 的实现

public class LoginServiceImpl implements ILoginService{
    @Override
    public String login(String username, String password) {if(username.equals("admin")&&password.equals("admin")){return "SUCCESS";}
        return "FAILED";
    }
}

user-service-consumer

public class App 
{public static void main( String[] args ){
        ILoginService loginService=null;

        System.out.println(loginService.login("admin","admin"));
    }
}

问题来了,当初 user-service-consumer 作为服务消费者,如何去调用近程服务 user-service-provider 呢?

依照后面对于服务近程通信的原理来说,服务提供方必然须要将服务公布到网络上,并且提供对应的拜访协定。而服务生产端必然须要基于这个协定来进行拜访。

这个时候,dubbo 这个中间件就派上用场了,它的最根本作用就是提供服务的公布和服务的近程拜访。

引入 Dubbo 公布服务

  • 引入 dubbo 依赖包

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.7.8</version>
    </dependency>
  • 在 /src/main/resource/META-INF/spring 目录下增加 application.xml 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
           xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        <!-- 提供方利用信息,用于计算依赖关系 -->
        <dubbo:application name="user-service"/>
        <!-- 应用 multicast 播送注册核心裸露服务地址 -->
        <dubbo:registry address="N/A" />
        <!-- 用 dubbo 协定在 20880 端口裸露服务 -->
        <dubbo:protocol name="dubbo" port="20880" />
        <!-- 申明须要裸露的服务接口 -->
        <dubbo:service interface="com.gupaoedu.demo.ILoginService" ref="loginService" />
        <!-- 和本地 bean 一样实现服务 -->
        <bean id="loginService" class="com.gupaoedu.demo.LoginServiceImpl" />
    
    </beans>
  • 启动服务

    public class App 
    {public static void main( String[] args ){Main.main(args);
        }
    }
  • 启动胜利后,会在控制台看到如下日志

    信息:  [DUBBO] Export dubbo service com.gupaoedu.demo.ILoginService to url dubbo://192.168.1.104:20880/com.gupaoedu.demo.ILoginService?anyhost=true&application=user-service&bind.ip=192.168.1.104&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.gupaoedu.demo.ILoginService&methods=login&pid=24280&release=2.7.8&side=provider&timestamp=1596550697070, dubbo version: 2.7.8, current host: 192.168.152.1
    八月 04, 2020 10:18:17 下午 org.apache.dubbo.remoting.transport.AbstractServer info
    信息:  [DUBBO] Start NettyServer bind /0.0.0.0:20880, export /192.168.1.104:20880, dubbo version: 2.7.8, current host: 192.168.152.1

通过上述步骤,就示意 ILoginService 曾经公布到了网络上,基于 NettyServer 的模式,默认监听 20880 端口

服务消费者引入 dubbo

  • 增加 jar 包依赖

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.7.8</version>
    </dependency>
  • 在 /src/main/resources/META-INF/spring 目录下增加 application.xml 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
           xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        <!-- 提供方利用信息,用于计算依赖关系 -->
        <dubbo:application name="user-service-consumer"/>
        <!-- 应用 multicast 播送注册核心裸露服务地址 -->
        <dubbo:registry address="N/A" />
        <dubbo:reference id="loginService" interface="com.gupaoedu.demo.ILoginService"/>
    </beans>
  • 批改 main 办法

    • 通过 ApplicationContext 加载 spring 的配置文件
    • 从容器中取得一个 ILoginService 的 bean
    public class App 
    {public static void main( String[] args ){
            ILoginService loginService=null;
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:META-INF/spring/application.xml");
            loginService=applicationContext.getBean(ILoginService.class);
    
            System.out.println(loginService.login("admin","admin"));
        }
    }

指定服务提供端的 url

在上述的配置实现之后,运行我的项目后发现会提醒如下谬误

IllegalStateException: No such any registry to reference com.gupaoedu.demo.ILoginService on the consumer 192.168.152.1 use dubbo version 2.7.8, please config <dubbo:registry address="..." /> to your spring config.

起因是,咱们配置的 dubbo:registry 指定的注册核心是 N /A,示意没有配置注册核心。

其次,咱们也没有明确的指明服务提供者在什么地位。因而解决这个问题的办法有两种

  • 指向服务提供者的地址
  • 配置服务注册核心,把服务提供者注册到注册核心,而后服务消费者指向注册核心从注册核心获取服务地址

批改形式如下,批改服务消费者中 application.xml 中的 dubbo:reference。

 <dubbo:reference id="loginService" interface="com.gupaoedu.demo.ILoginService"
     url="dubbo://192.168.1.104:20880/com.gupaoedu.demo.ILoginService"/>

总结

简略总结一下下面的整个过程,其实不难发现,Dubbo 这个中间件为咱们提供了服务近程通信的解决方案。通过 dubbo 这个框架,能够开发者疾速高效的构建微服务架构下的近程通信实现。

不晓得大家是否发现,咱们在应用 dubbo 公布服务,或者生产服务的时候,全程都是采纳 spring 的配置来实现的,这样的益处是咱们在学习或者应用 dubbo 时,如果你用过 spring 这个框架,那么对于它的学习难度会大大的升高。而且咱们也能够看到,dubbo 是齐全集成 Spring 的,因而后续咱们去剖析 dubbo 的源码时,还是会有一些和 spring 无关的内容。

而且如果大家之前学习过我手写 RPC 的那节课,也根本能猜测到它的整个实现构造,大家无妨大胆的去猜想 dubbo 的一些实现细节,以助于后续在深度学习 dubbo 时更好的了解。

引入注册核心

Dubbo 并不仅仅只是一个 RPC 框架,他还是一个服务治理框架,它提供了对服务的对立治理、以及服务的路由等性能。

在下面的案例中,咱们只是拆穿了 Dubbo 作为 RPC 通信的点对点服务,然而就像咱们后面在学习 spring cloud 的内容一样,服务多了当前,如何治理和保护,以及动静发现呢?

而且,从 Dubbo 的架构图中能够看到,Dubbo 人造就反对服务注册与发现,官网最早举荐的服务注册核心是 zookeeper,当然,目前 dubbo 可能反对的注册核心曾经十分多了,比方

consul、etcd、nacos、sofa、zookeeper、eureka、redis 等等,很显然,Dubbo 曾经在往一个独立微服务解决方案的生态在倒退。

集成 Zookeeper 作为服务注册核心

  • 增加 zookeeper 的 jar 包依赖

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>2.7.8</version>
    </dependency>
  • 批改服务提供者和服务消费者的配置

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

集成 Nacos 作为服务注册核心

  • 启动 nacos

    docker run --name nacos -d -p 8848:8848 --privileged=true --restart=always -e JVM_XMS=512m -e JVM_XMX=2048m -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /home/nacos/logs:/home/nacos/logs nacos/nacos-server
    • privileged: 应用该参数,container 内的 root 领有真正的 root 权限。否则,container 内的 root 只是内部的一个普通用户权限。
    • 当 Docker 重启时,容器主动重启
    • PREFER_HOST_MODE: ip #如果反对主机名能够应用 hostname, 否则应用 ip,默认也是 ip
  • 增加依赖

    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>1.2.1</version>
    </dependency>
  • 批改配置

    <dubbo:registry address="nacos://192.168.216.128:8848" timeout="10000" />

Dubbo Spring Cloud

既然咱们讲的是 Spring Cloud Alibaba 这个专题,那么咱们就有必要去理解一下 Dubbo 是如何集成 Spring Cloud 去应用的。

Dubbo Spring Cloud 是构建在原生的 Spring Cloud 之上,涵盖了 Spring Cloud 原生个性,而且绝对于 Spring Cloud 原生治理来说,Dubbo Spring Cloud 提供了更加稳固和成熟的实现。

具体的个性比照如下:

为什么叫 Dubbo Spring Cloud,而不是 Spring Cloud Dubbo 呢,在我看来,Dubbo 自身是自成一个生态体系,并且在自身的服务治理以及成熟度上要比 Spring cloud 更加突出。

所以实际上 Dubbo 整合 Spring Cloud,是 Dubbo 这个成熟的生态去拥抱 spring cloud 的规范体系。

Dubbo Spring Cloud 基于 Dubbo Spring Boot 2.7.1[1] 和 Spring Cloud 2.x 开发,无论开发人员是 Dubbo 用户还是 Spring Cloud 用户,都能轻松地驾驭,并以靠近“零”老本的代价使利用向上迁徙

从 2.7.0 开始,Dubbo Spring Boot 与 Dubbo 在版本上保持一致

接下来,咱们能够去利用 Dubbo Spring Cloud 来做一个简略的案例实现

创立一个我的项目

  • 创立一个 spring-cloud-dubbo-example 的 maven 工程
  • 别离增加三个模块

    • spring-cloud-dubbo-sample-api
    • spring-cloud-dubbo-sample-provider
    • spring-cloud-dubbo-sample-consumer

其中前面两个模块都是 spring boot 的利用。

批改 spring-cloud-dubbo-sample-provider 这个模块中。

  • 将 dependencyManagement 局部的依赖挪动到 parent pom.xml
  • 批改 spring-cloud-dubbo-sample-provider 中的 pom.xml, 减少 parent 模块的依赖

    <parent>
        <groupId>com.gupaoedu.dubbo</groupId>
        <artifactId>spring-cloud-dubbo-example</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
  • 增加 maven 依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
    <dependency>
        <groupId>com.gupaoedu.dubbo</groupId>
        <version>1.0-SNAPSHOT</version>
        <artifactId>spring-cloud-dubbo-sample-api</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

定义服务接口

在 spring-boot-dubbo-sample-api 模块中,定义接口

public interface IHelloService {String sayHello();
}

实现服务

在 spring-boot-dubbo-sample-provider 中,实现 IHelloService 接口

public class HelloServiceImpl implements IHelloService{

    @Override
    public String sayHello() {return "Hello GuPao";}
}

增加 @EnableDiscoveryClient 注解

@EnableDiscoveryClient
@SpringBootApplication
public class SpringCloudDubboSampleProviderApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudDubboSampleProviderApplication.class, args);
    }

}

配置 dubbo 服务公布

  • 在服务实现类中增加 @Service 注解

    @Service
    public class HelloServiceImpl implements IHelloService{
    
        @Override
        public String sayHello() {return "Hello GuPao";}
    }
  • 配置 dubbo 提供方信息

    # dubbo 服务扫描根底包门路
    dubbo.scan.base-packages=com.gupaoedu.dubbo.springclouddubbosampleprovider
    
    dubbo.protocol.id=dubbo
    # Dubbo 服务裸露的协定配置,其中子属性 name 为协定名称,port 为协定端口(-1 示意自增端口,从 20880 开始)dubbo.protocol.name=dubbo
    dubbo.protocol.port=-1
    
    spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
    • dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包
    • dubbo.protocol : Dubbo 服务裸露的协定配置,其中子属性 name 为协定名称,port 为协定端口(-1 示意自增端口,从 20880 开始)
    • dubbo.registry : Dubbo 服务注册核心配置,其中子属性 address 的值 “spring-cloud://localhost”,阐明挂载到 Spring Cloud 注册核心
    • spring.cloud.nacos.discovery : Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口

版本标准

我的项目的版本号格局为 x.x.x 的模式,其中 x 的数值类型为数字,从 0 开始取值,且不限于 0~9 这个范畴。我的项目处于孵化器阶段时,第一位版本号固定应用 0,即版本号为 0.x.x 的格局。

因为 Spring Boot 1 和 Spring Boot 2 在 Actuator 模块的接口和注解有很大的变更,且 spring-cloud-commons 从 1.x.x 版本升级到 2.0.0 版本也有较大的变更,因而咱们采取跟 SpringBoot 版本号统一的版本:

  • 1.5.x 版本实用于 Spring Boot 1.5.x
  • 2.0.x 版本实用于 Spring Boot 2.0.x
  • 2.1.x 版本实用于 Spring Boot 2.1.x
  • 2.2.x 版本实用于 Spring Boot 2.2.x

构建服务消费者

  • 增加 jar 包依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>com.gupaoedu.dubbo</groupId>
        <version>1.0-SNAPSHOT</version>
        <artifactId>spring-cloud-dubbo-sample-api</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  • 增加配置文件

    spring.application.name=spring-cloud-dubbo-sample-consumer
    dubbo.application.name=spring-cloud-dubbo-sample-consumer
    
    dubbo.cloud.subscribed-services=spring-cloud-dubbo-sample-provider
    spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848

    除利用名称 spring.application.name 存在差别外,spring-cloud-dubbo-client-sample 新增了属性 dubbo.cloud.subscribed-services 的设置。并且该值为服务提供方利用 “spring-cloud-dubbo-sample-provider”。

    它的次要作用是服务生产方订阅服务提供方的利用名称的列表,若需订阅多利用,应用 “,” 宰割。不举荐应用默认值为 “*”,它将订阅所有利用。

  • 编写测试代码

    @RestController
    @EnableDiscoveryClient
    @SpringBootApplication
    public class SpringCloudDubboSampleConsumerApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudDubboSampleConsumerApplication.class, args);
        }
        @Reference
        IHelloService helloService;
    
        @GetMapping("/say")
        public String say(){return helloService.sayHello();
        }
    
    }

    # 多注册核心的反对

dubbo 绝对于 spring cloud 来说,它的弱小之处在于,提供了很多不同场景的性能反对,比方多注册核心的反对。

所谓的多注册核心,就是指 dubbo 能够同时配置多个注册核心的地址,而后针对于不同类型的服务注册到不同的注册核心上。

Dubbo 多注册核心能够反对几种场景

一个服务部署到多个注册核心

基于 spring cloud 的配置形式

  • 增加 jar 包依赖

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>2.7.8</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
            <exclusion>
                <artifactId>log4j</artifactId>
                <groupId>log4j</groupId>
            </exclusion>
        </exclusions>
    </dependency>
  • 批改 application 配置

    dubbo.registries.registry1.address=nacos://192.168.216.128:8848
    dubbo.registries.registry1.timeout=10000
    dubbo.registries.registry2.address=zookeeper://192.168.216.128:2181
    dubbo.registries.registry2.timeout=10000
    
    #spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
    spring.cloud.nacos.discovery.register-enabled=false
    spring.cloud.nacos.discovery.watch.enabled=false
    spring.cloud.service-registry.auto-registration.enabled=false
    • spring.cloud.service-registry.auto-registration.enabled 敞开 spring cloud 的主动注册
    • spring.cloud.nacos.discovery.watch.enabled/spring.cloud.nacos.discovery.register-enabled 敞开 nacos 的服务注册和监听

    这么做的目标是,躲避 spring cloud 自身的服务注册发现机制,走 dubbo 自身的服务注册与发现

  • 批改服务配置

    @Service(registry = {"registry1","registry2"})
    public class HelloServiceImpl implements IHelloService{
    
        @Override
        public String sayHello() {return "Hello GuPao";}
    }

多注册核心的援用

  • 批改生产端的 application.properties

    dubbo.registries.registry1.address=nacos://192.168.216.128:8848
    dubbo.registries.registry1.timeout=10000
    dubbo.registries.registry2.address=zookeeper://192.168.216.128:2181
    dubbo.registries.registry2.timeout=10000
    
    spring.cloud.nacos.discovery.register-enabled=false
    spring.cloud.nacos.discovery.watch.enabled=false
    spring.cloud.service-registry.auto-registration.enabled=false
  • 增加 jar 包依赖

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>2.7.8</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
            <exclusion>
                <artifactId>log4j</artifactId>
                <groupId>log4j</groupId>
            </exclusion>
        </exclusions>
    </dependency>

基于 spring boot 集成 Dubbo 形式

实际上,在 dubbo spring cloud 的应用形式中,对于配置多个服务注册核心不是很敌对而且还有一些潜在的问题,毕竟 dubbo 和 spring cloud 两个实质上是属于齐全不同的生态耦合在一起,必然会导致一些兼容问题。比方刚刚咱们去配置的这些多注册核心的反对,它须要去敞开 spring cloud 自身的服务主动注册和发现的反对,实质上就是在两个生态中抉择其中一个生态作为次要形式来应用。

所以,如果是在 spring cloud 的生态中,能够尽量减少对于 dubbo 自身灵活性的应用,拥抱 spring cloud 的规范生态,当然如果心愿以 dubbo 作为独立的生态来应用,大家能够采纳 spring boot+Dubbo 来集成,

这里同样也给大家疾速构建一下。

另外,dubbo 集成到 spring boot 中还有一个益处,就是它能够继承 spring boot 自身的个性

  • 主动拆卸(注解驱动、主动拆卸)
  • production-ready(平安机制、衰弱检测、内部化配置)

创立我的项目构造

创立根底的我的项目构造

  • spring-boot-dubbo-example [maven]

    • spring-boot-dubbo-sample-api [maven]
    • spring-boot-dubbo-sample-provider [spring boot]
    • spring-boot-dubbo-sample-consumerp [spring-boot]

增加 jar 包依赖

从 2.7 开始,dubbo 的版本和 dubbo-spring-boot 的版本是保持一致的,所以大家不必再去放心版本的问题。

<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.7</version>
</dependency>
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.2.1</version>
</dependency>

增加服务以及公布

@DubboService
public class SayHelloServiceImpl implements ISayHelloService{
    @Override
    public String sayHello() {return "Hello GuPaoEdu.com";}
}
spring.application.name=spring-boot-dubbo-sample-provider

dubbo.registry.address=nacos://192.168.216.128:8848
dubbo.scan.base-packages=com.gupaoedu.springboot.dubbo.springbootdubbosampleprovider.service

dubbo.protocol.name=dubbo
dubbo.protocol.port=-1

编写服务援用代码

  • 增加 jar 包依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.gupaoedu.com</groupId>
        <version>1.0-SNAPSHOT</version>
        <artifactId>spring-boot-dubbo-sample-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>1.2.1</version>
    </dependency>
  • 增加 web 测试类

    @DubboReference
    ISayHelloService sayHelloService;
    
    @GetMapping("/get")
    public String get(){return sayHelloService.sayHello();
    }
    dubbo.registry.address=nacos://192.168.216.128:8848

不同服务注册到不同的注册核心

从下面的配置能够发现,咱们开能够针对不同的服务配置到不同的注册核心,这个就不再浪费时间去演示了。

多个注册核心的集群

如果一个服务消费者援用了多个注册核心,那么这个时候服务消费者首先要做的就是先针对注册核心的负载平衡,而后失去一个指标注册核心之后,再从指标注册核心上取得服务提供者的地址列表再进行集群拜访,实现原理如下图所示

当然,有三种形式来指定注册核心的负载平衡配置

  • 指定优先级

    <!-- 来自 preferred=“true”注册核心的地址将被优先选择,只有该核心无可用地址时才 Fallback 到其余注册核心 -->
    <dubbo:registry address="zookeeper://${zookeeper.address1}" preferred="true" />
  • 同 zone 优先

    <!-- 选址时会和流量中的 zone key 做匹配,流量会优先派发到雷同 zone 的地址 -->
    <dubbo:registry address="zookeeper://${zookeeper.address1}" zone="beijing" />
  • 权重轮询

    <!-- 来自北京和上海集群的地址,将以 10:1 的比例来调配流量 -->
    <dubbo:registry id="beijing" address="zookeeper://${zookeeper.address1}" weight=”100“/>
    <dubbo:registry id="shanghai" address="zookeeper://${zookeeper.address2}" weight=”10“/>

接口多版本反对

平时咱们在开发接口的时候,可能会面临到一个接口的批改,然而这个时候因为线上会有一些我的项目正在应用这个接口,如果间接批改,很可能会对线上的服务造成比拟大的影响。

因而对于这种状况,dubbo 提供了接口版本的反对。

具体的配置形式

  • 服务端针对同一个接口提供不同版本的实现
  • 并在 dubboservice 注解中配置版本的申明

    @DubboService(registry = {"registry1","registry2"},version = "1.0")
  • 服务生产端指定生产版本号

    @DubboReference(registry = {"registry1","registry2"},version = "2.0")
    ISayHelloService sayHelloService;

多协定的反对

当公司本来采纳其余的 rpc 框架,这个时候如果想迁徙到 dubbo 这个框架上来,那么 Dubbo 提供的多协定反对就可能提供简直零老本的迁徙。

对于一个服务,能够同时公布多种不同协定的接口,也能够针对不同的接口公布不同的协定类型。并且从 2.7 开始,dubbo 对于一些支流的协定做了反对,目前曾经反对的协定有

dubbo 协定、hessian 协定、http 协定、thrift、rmi、webservice、grpc、rest 等。首次之外,dubbo 还提供了非常灵活的可扩展性机制,对于有定制化需要或者目前正在应用的协定,dubbo 不反对的公司,是能够本人去进行扩大。

整体的灵活性以及可插拔性的个性,相比 spring cloud 来说,更加弱小。

JAX-RS 协定阐明

Dubbo 中的 REST(表述性资源转移)反对,是基于 JAX-RS2.0(Java API for RESTful Web Services)来实现的。

REST 是一种架构格调,简略来说就是对于 api 接口的束缚,基于 URL 定位资源,应用 http 动词(GET/POST/DELETE)来形容操作

REST 很早就提出来了,在晚期开发人员为了实现 REST,会应用各种工具来实现,比方 Servlets 就常常用来开发 RESTful 的程序。随着 REST 被越来越多的开发人员采纳,所以 JCP(Java community process)提出了 JAX-RS 标准,并且提供了一种新的基于注解的形式来开发 RESTful 服务。有了这样的一个标准,使得开发人员不须要关怀通信层的货色,只须要关注资源以以及数据对象。

JAX-RS 标准的实现有:Apache CXF、Jersey(由 Sun 公司提供的 JAX-RS 的参考实现)、RESTEasy(jboss 实现)等。

而 Dubbo 外面实现的 REST 就是基于 Jboss 提供的 RESTEasy 框架来实现的

SpringMVC 中的 RESTful 实现咱们用得比拟多,它也是 JAX-RS 标准的一种实现

增加 REST 反对

  • 增加 jar 包依赖

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>3.13.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.13.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.4.19.v20190610</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.4.19.v20190610</version>
    </dependency>
  • 批改配置文件

    dubbo.protocols.dubbo.name=dubbo
    dubbo.protocols.dubbo.port=-1
    
    dubbo.protocols.rest.name=rest
    dubbo.protocols.rest.port=8888
    dubbo.protocols.rest.server=jetty
  • 批改 api 的接口定义

    @Path("/")
    public interface ISayHelloService {
    
        @GET
        @Path("say")
        String sayHello();}

版权申明:本博客所有文章除特地申明外,均采纳 CC BY-NC-SA 4.0 许可协定。转载请注明来自 Mic 带你学架构
如果本篇文章对您有帮忙,还请帮忙点个关注和赞,您的保持是我一直创作的能源。欢送关注同名微信公众号获取更多技术干货!

退出移动版