Dubbo是阿里开源的的rpc框架,现已成为Apache的顶级项目。Dubbo在国内的大公司中使用较多,具有良好的服务治理能力。
在阿里停止维护一段时间后,2017年又重新开始维护,2.x的最新版本为2.7版本。2021年Dubbo更新到了3.0版本,相对于2.x版本,有了巨大的变化。博主将通过两篇文章分别对dubbo2和dubbo3进行简单的介绍。
本文主要介绍dubbo2。
RPC框架原理与实践
Dubbo原理与实践(1)
Dubbo原理与实践(2)
架构
dubbo架构如下图所示:
节点角色说明
- Provider,暴露服务的服务提供方
- Consumer,调用远程服务的服务消费方
- Registry,服务注册与发现的注册中心
- Monitor,统计服务的调用次数和调用时间的监控中心
- Container,服务运行容器
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。
连通性
- 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
- 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
- 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销。
- 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销。
- 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外。
- 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者。
- 即使注册中心和监控中心全部宕机,也不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表。
- 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者。
健壮性
- 监控中心宕掉不影响使用,只是丢失部分采样数据。
- 注册中心宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务。
- 注册中心对等集群,任意一台宕掉后,将自动切换到另一台。
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯。
- 服务提供者无状态,任意一台宕掉后,不影响使用。
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复。
伸缩性
- 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心。
- 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者。
升级性
当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力。下图是未来可能的一种架构:
dubbo2的服务发现
实现服务发现的方式有很多种,Dubbo 提供的是一种基于客户端的服务发现机制,需要部署额外的第三方注册中心组件来协调服务发现过程,如常用的 Nacos、Consul、Zookeeper 等,Dubbo 自身也提供了对多种注册中心组件的对接,可以灵活选择。
服务发现的一个核心组件是注册中心,Provider 注册地址到注册中心,Consumer 从注册中心读取和订阅 Provider 地址列表。 因此,要启用服务发现,需要为 Dubbo 增加注册中心配置:
以 dubbo-spring-boot-starter 使用方式为例,增加 registry 配置
# application.properties
dubbo
registry
address: zookeeper://127.0.0.1:2181
dubbo3引入了应用级服务发现模型,一方面是为了适配云原生微服务的变革,另一方面也提高了性能和可伸缩性。
用法
本地配置Spring服务
<bean id=“xxxService” class=“com.xxx.XxxServiceImpl” />
<bean id=“xxxAction” class=“com.xxx.XxxAction”>
<property name=“xxxService” ref=“xxxService” />
</bean>
远程服务 Spring 配置
在本地服务的基础上,只需做简单配置,即可完成远程化:
- 将上面的 local.xml 配置拆分成两份,将服务定义部分放在服务提供方 remote-provider.xml,将服务引用部分放在服务消费方 remote-consumer.xml。
- 并在提供方增加暴露服务配置
<dubbo:service>
,在消费方增加引用服务配置<dubbo:reference>
。
remote-provider.xml:
<!-- 和本地服务一样实现远程服务 -->
<bean id=“xxxService” class=“com.xxx.XxxServiceImpl” />
<!-- 增加暴露远程服务配置 -->
<dubbo:service interface=“com.xxx.XxxService” ref=“xxxService” />
remote-consumer.xml:
<!-- 增加引用远程服务配置 -->
<dubbo:reference id=“xxxService” interface=“com.xxx.XxxService” />
<!-- 和本地服务一样使用远程服务 -->
<bean id=“xxxAction” class=“com.xxx.XxxAction”>
<property name=“xxxService” ref=“xxxService” />
</bean>
下面贴一个简单的例子。
创建两个SpringBoot项目,引入dubbo相关的依赖。其中一个是服务提供者,一个是服务消费者,均通过xml来配置dubbo。 注意3.5以上版本的zk启动时会占用8080端口。
dubbo-provider.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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-provider" />
<!-- 服务注册 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="cn.howe.dubbo.demo.DemoService" ref="demoService" timeout="5000"/>
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="cn.howe.dubbo.demo.DemoServiceImpl" />
</beans>
dubbo-consumer.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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="dubbo-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" interface="cn.howe.dubbo.demo.DemoService" />
</beans>
启动项目的时候,需要在主类头上加上注解:
@SpringBootApplication
@ImportResource(value = {"classpath*:dubbo-provider.xml"})
和
@SpringBootApplication
@ImportResource(value = {"classpath*:dubbo-consumer.xml"})
除了这种方式以外,也可以通过dubbo-spring-boot-starter的方式来启动项目,并开启@EnableDubbo注解。网上资料很多,这里就不详细说了。
参考资料
[1]. https://dubbo.apache.org/zh/docs/v2.7/