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

技术分布式服务治理框架Dubbo的前世今生及应用实战 分布式服务治理框架Dubbo的前世今生及应用实战Dubbo的出现背景
Dubbo从开源到现在,已经出现了接近10年时间,在国内各大企业被广泛应用。

分布式服务治理框架Dubbo的过去和应用

Dubbo的出现背景

Dubbo自开源以来已存在近10年,在国内各大企业得到广泛应用。它值得追求什么魔力?这篇文章会给你详细的解释。

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

当企业开始大规模服务时,远程通信带来的弊端越来越明显。例如

服务链接越来越长。如何跟踪和监控服务环节?

服务的大规模集群使得服务需要依赖第三方注册中心来解决服务发现和服务感知问题。

服务之间的异常通信需要一种保护机制来防止节点故障导致大规模系统故障,因此需要有一种容错机制。

大规模集群服务将使客户端能够引入负载平衡机制来实现请求分发。

对于服务治理的这些需求,传统的RPC技术在这样的场景下显得有些不足,于是很多企业开始开发自己的RPC框架,比如HSF和杜博都是如此;阿里的。JD.COM的JSF框架、当当网的配音盒、新浪的motan、蚂蚁金服的沙发等等。

有技术输出能力的公司会开发适合自己场景的rpc框架,要么从0到1,要么基于现有思路结合公司业务特点。然而,没有技术输出能力的公司在满足服务治理的需求时,会优先考虑那些成熟的开源框架。杜博就是其中之一。

Dubbo主要是一种分布式服务治理解决方案,那么什么是服务治理服务治理主要是解决大规模服务后服务之间的路由、负载均衡、容错机制和服务降级等问题。Dubbo不仅实现了远程服务通信,还解决了服务路由、负载、降级和容错等功能。

Dubbo的发展历史

Dubbo是阿里巴巴使用的分布式服务治理框架。2012年开业。由于Dubbo已经在公司得到验证,相对成熟,短时间内被很多互联网公司使用。另外,来自阿里的很多技术巨头作为技术框架进入各种创业公司后,都以Dubbo作为主要的RPC框架,这使得Dubbo成为很多互联网公司的首选。而且很多公司会根据自己的业务特点对dubbo进行优化和改进,所以衍生出了很多版本,比如JD.COM的JSF、新浪的Motan、当当的dubbox。

2014年10月,Dubbo停止维修。后来在2017年9月,阿里宣布重启杜博,并为长期投资杜博做准备。在这期间,Dubbo做了很多更新,目前版本已经达到了2.7。

2018年1月8日,Dubbo创始人之一梁飞透露了Dubbo 3.0正在Dubbo交换集团建设的消息。Dubbo 3.0内核与Dubbo2.0完全不同,但与Dubbo 2.0兼容。Dubbo 3.0将支持可选的服务网格。

2018年2月,杜布博向阿帕奇捐赠。此外,阿里巴巴对Spring Cloud的完善阿里巴巴的生态和Spring Cloud团队对阿里巴巴整个服务治理生态的支持,因此Dubbo仍将是未来大多数国内公司的首选。

Dubbo的整体架构

Dubbo的使用

首先,建立两个maven项目。

用户服务

用户服务api

用户服务提供商

用户服务消费者

user-service-api

用户服务提供了一个公共的服务契约,它提供了用户服务的外部服务。

公共接口ILoginService {

字符串登录(字符串用户名、字符串密码);

}

user-service-provider

在用户服务提供者服务中,提供ILoginService的实现。

公共类LoginServiceImpl实现了ILoginService{

@覆盖

公共字符串登录(字符串用户名、字符串密码){ 0

if(username . equals(' admin ')password . equals(' admin ')(

返回“SUCCESS”;

}

返回“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
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo/artifactId
        version2.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  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.ILoginServiceanyhost=trueapplication=user-servicebind.ip=192.168.1.104bind.port=20880deprecated=falsedubbo=2.0.2dynamic=truegeneric=falseinterface=com.gupaoedu.demo.ILoginServicemethods=loginpid=24280release=2.7.8side=providertimestamp=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
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo/artifactId
        version2.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  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  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
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo-dependencies-zookeeper/artifactId
        version2.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
        groupIdcom.alibaba.nacos/groupId
        artifactIdnacos-client/artifactId
        version1.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提供了更加稳定和成熟的实现。

具体的特性对比如下:

![image-20200804224645852](E:\教研-课件\vip课程\第四轮\分布式微服务\5 第五章 Spring Cloud Alibaba微服务生态\01 第一节 微服务治理之Dubbo的基本认识\第一节 微服务治理之Dubbo的基本认识.assets\image-20200804224645852.png)

为什么叫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
        groupIdcom.gupaoedu.dubbo/groupId
        artifactIdspring-cloud-dubbo-example/artifactId
        version1.0-SNAPSHOT/version
    /parent
    
  • 添加maven依赖

    dependency
        groupIdcom.alibaba.cloud/groupId
        artifactIdspring-cloud-starter-dubbo/artifactId
    /dependency
    dependency
        groupIdcom.gupaoedu.dubbo/groupId
        version1.0-SNAPSHOT/version
        artifactIdspring-cloud-dubbo-sample-api/artifactId
    /dependency
    dependency
        groupIdcom.alibaba.cloud/groupId
        artifactIdspring-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
        groupIdcom.alibaba.cloud/groupId
        artifactIdspring-cloud-starter-dubbo/artifactId
    /dependency
    dependency
        groupIdorg.springframework.boot/groupId
        artifactIdspring-boot-actuator/artifactId
    /dependency
    dependency
        groupIdcom.gupaoedu.dubbo/groupId
        version1.0-SNAPSHOT/version
        artifactIdspring-cloud-dubbo-sample-api/artifactId
    /dependency
    dependency
        groupIdcom.alibaba.cloud/groupId
        artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId
    /dependency
    dependency
        groupIdorg.springframework.boot/groupId
        artifactIdspring-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
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo-dependencies-zookeeper/artifactId
        version2.7.8/version
        exclusions
            exclusion
                groupIdorg.slf4j/groupId
                artifactIdslf4j-log4j12/artifactId
            /exclusion
            exclusion
                artifactIdlog4j/artifactId
                groupIdlog4j/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
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo-dependencies-zookeeper/artifactId
        version2.7.8/version
        exclusions
            exclusion
                groupIdorg.slf4j/groupId
                artifactIdslf4j-log4j12/artifactId
            /exclusion
            exclusion
                artifactIdlog4j/artifactId
                groupIdlog4j/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
    groupIdorg.apache.dubbo/groupId
    artifactIddubbo-spring-boot-starter/artifactId
    version2.7.7/version
/dependency
dependency
    groupIdcom.alibaba.nacos/groupId
    artifactIdnacos-client/artifactId
    version1.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
        groupIdorg.springframework.boot/groupId
        artifactIdspring-boot-starter-web/artifactId
    /dependency
    dependency
        groupIdcom.gupaoedu.com/groupId
        version1.0-SNAPSHOT/version
        artifactIdspring-boot-dubbo-sample-api/artifactId
    /dependency
    dependency
        groupIdorg.apache.dubbo/groupId
        artifactIddubbo-spring-boot-starter/artifactId
        version2.7.7/version
    /dependency
    dependency
        groupIdcom.alibaba.nacos/groupId
        artifactIdnacos-client/artifactId
        version1.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  address="zookeeper://${zookeeper.address1}" weight=”100“ /
    dubbo:registry  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
        groupIdorg.jboss.resteasy/groupId
        artifactIdresteasy-jaxrs/artifactId
        version3.13.0.Final/version
    /dependency
    dependency
        groupIdorg.jboss.resteasy/groupId
        artifactIdresteasy-client/artifactId
        version3.13.0.Final/version
    /dependency
    dependency
        groupIdorg.eclipse.jetty/groupId
        artifactIdjetty-server/artifactId
        version9.4.19.v20190610/version
    /dependency
    dependency
        groupIdorg.eclipse.jetty/groupId
        artifactIdjetty-servlet/artifactId
        version9.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带你学架构
如果本篇文章对您有帮助,还请帮忙点个关注和赞,您的坚持是我不断创作的动力。欢迎关注「跟着Mic学架构」公众号公众号获取更多技术干货!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/136279.html

(0)

相关推荐

  • Git操作命令

    技术Git操作命令 Git操作命令1、新建代码库# 公众号:AllTests软件测试# 在当前目录新建一个Git代码库
    $ git init# 新建一个目录,将其初始化为Git代码库
    $ git ini

    礼包 2021年11月23日
  • 归并排序和逆序对数量

    技术归并排序和逆序对数量 归并排序和逆序对数量归并排序
    #includeiostreamusing namespace std;
    const int N = 100010;
    int q[N];
    int

    礼包 2021年11月5日
  • JS构造函数和实例化的关系及原型引入举例分析

    技术JS构造函数和实例化的关系及原型引入举例分析这篇文章主要介绍“JS构造函数和实例化的关系及原型引入举例分析”,在日常操作中,相信很多人在JS构造函数和实例化的关系及原型引入举例分析问题上存在疑惑,小编查阅了各式资料,

    攻略 2021年11月29日
  • golang 如何识别文本格式(golang读取txt文件一次读取一行)

    技术Golang怎么读取单行超长的文本这篇文章主要介绍“Golang怎么读取单行超长的文本”,在日常操作中,相信很多人在Golang怎么读取单行超长的文本问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望

    攻略 2021年12月22日
  • Python用哪些工具好

    技术Python用哪些工具好这篇文章主要介绍了Python用哪些工具好,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、最强终端:Upterm本来想推荐

    攻略 2021年10月28日
  • 最早的汽车,世界上成立最早的汽车品牌是

    技术最早的汽车,世界上成立最早的汽车品牌是世界上最早的汽车应该是奔驰l770年法国人尼古拉斯古诺汽车诞生之前马车就是人类最好的陆上交通工具。l770年法国人尼古拉斯古诺(1725一1804)将蒸汽机装在板车上最早的汽车,

    生活 2021年10月21日