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提供了更加稳定和成熟的实现。

具体的特性对比如下:

![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>
    <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带你学架构

如果本篇文章对您有帮助,还请帮忙点个关注和赞,您的坚持是我不断创作的动力。欢迎关注「跟着Mic学架构」公众号公众号获取更多技术干货!

分布式服务治理框架Dubbo的前世今生及应用实战的更多相关文章

  1. 分布式服务治理框架dubbo

    Dubbo最主要功能有两个 1 RPC调用 2 SOA服务治理方案 Dubbo的架构 Dubbo常见的注册中心有2中,zookeeper以及redis 这篇文章讲解的是采用的zookeeper,要求读 ...

  2. 服务治理框架dubbo中zookeeper的使用

    Zookeeper提供了一套很好的分布式集群管理的机制,就是它这猴子那个几月层次型的目录树的数据结构,并对书中的节点进行有效的管理,从而可以设计出多种多样的分布式的数据管理模型:下面简要介绍下zook ...

  3. Java框架Spring Boot & 服务治理框架Dubbo & 应用容器引擎Docker 实现微服务发布

    微服务系统架构实践 开发语言Java 8 框架使用Spring boot 服务治理框架Dubbo 容器部署Docker 持续集成Gitlab CI 持续部署Piplin 注册中心Zookeeper 服 ...

  4. 个人学习分布式专题(二)分布式服务治理之Dubbo框架

    目录 Dubbo框架 1.1 Dubbo是什么 1.2 Dubbo企业级应用示例(略) 1.3 Dubbo实现原理及架构剖析 1.4 Dubbo+Spring集成 Dubbo框架 1.1 Dubbo是 ...

  5. 美团分布式服务通信框架及服务治理系统OCTO

     一.什么是OCTO 定义: OCTO是美团的分布式服务通信框架及服务治理系统,属于公司级基础设施,目前尚未开源. 目标: 为公司所有业务提供统一的服务通信框架,使业务具备良好的服务运营能力,轻松实现 ...

  6. java使用netty模拟实现一个类dubbo的分布式服务调用框架

    本文较长,如果想直接看代码可以查看项目源码地址: https://github.com/hetutu5238/rpc-demo.git 要想实现分布式服务调用框架,我们需要了解分布式服务一般需要的功能 ...

  7. 美团 OCTO 分布式服务治理系统

    OCTO 是美团千亿调用量的分布式服务通信框架及服务治理的系统,可实现服务注册.服务自动发现.服务管理.容错处理.数据可视化.服务监控报警.服务分组等.本文总结了 OCTO 架构原理.Java 应用的 ...

  8. 服务治理框架:Spring Cloud Eureka

    最近在学习Spring Cloud的知识,现将服务治理框架 Spring Cloud Eureka 的相关知识笔记整理如下.[采用 oneNote格式排版]

  9. 京东云入选2019年度TOP100全球软件案例 新一代服务治理框架加速行业落地

    11月14日-17日, 2019TOP100全球软件案例研究峰会(TOP100summit)在北京国家会议中心举办.Top100summit是科技界一年一度的案例研究峰会,每年会秉承"从用户 ...

随机推荐

  1. ip_local_port_range 和 ip_local_reserved_ports

    问题:启动应用程序时,发现网络端口被占用,原因是什么?如何避免? 原因:Linux 系统设置了随机使用的端口范围  echo "40000  60000" > /proc/. ...

  2. 《基于SD-SEIR模型的实验室人员不安全行为传播研究》

    My Focus:基于SD-SEIR模型的实验室人员不安全行为的传播; 建模与实验仿真 Title: Study on Porpagation of Unsafe Bhavior of Laborat ...

  3. BF算法和KMP算法

    这两天复习数据结构(严蔚敏版),记录第四章串中的两个重要算法,BF算法和KMP算法,博主主要学习Java,所以分析采用Java语言,后面会补上C语言的实现过程. 1.Brute-Force算法(暴力法 ...

  4. uvm_subscriber

    subscriber是消费,用户的意思 uvm_subscriber主要作为coverage的收集方式之一 uvm_subscriber的代码非常简单,继承于uvm_component,再加上一个an ...

  5. 关于把RTL工程代码封装成IP时对define宏定义参数的处理

    在把RTL工程封装成IP的时候,如果工程中的代码中含有global include中定义的参数,则vivado不支持该参数文件的封装.出现IP_FLOW 19-4646的错误代码,解决方法: 1.在用 ...

  6. 前端面试手写代码——JS数组去重

    目录 1 测试用例 2 JS 数组去重4大类型 2.1 元素比较型 2.1.1 双层 for 循环逐一比较(es5常用) 2.1.2 排序相邻比较 2.2 查找元素位置型 2.2.1 indexOf ...

  7. 一步一步学ROP之gadgets和2free篇(蒸米spark)

    目录 一步一步学ROP之gadgets和2free篇(蒸米spark) 0x00序 0x01 通用 gadgets part2 0x02 利用mmap执行任意shellcode 0x03 堆漏洞利用之 ...

  8. redis 集群环境搭建

    原理: 1,每个Redis群集的节点都需要打开两个TCP连接,由于这两个连接就需要两个端口,分别是用于为客户端提供服务的常规Redis TCP命令端口(例如6379)以及通过将10000和命令端口相加 ...

  9. Lambda-让人又爱又恨的“->"

    写在前边 聊到Java8新特性,我们第一反应想到的肯定是Lambda表达式和函数式接口的出现.要说ta到底有没有在一定程度上"优化"了代码的简洁性呢?抑或是ta在一定程度上给程序员 ...

  10. Kubernetes Deployment 源码分析(二)

    概述startDeploymentController 入口逻辑DeploymentController 对象DeploymentController 类型定义DeploymentController ...