Dubbo
致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。
官网:http://dubbo.apache.org
RPC概述
RPC是远程过程调用(Remote Procedure Call)。 RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。
优点:
1、分布式设计
2、部署灵活
3、解构服务
4、扩展性强
有哪些RPC框架?
Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。
Motan:微博内部使用的 RPC 框架,于 2016 年对外开源,仅支持 Java 语言。
Tars:腾讯内部使用的 RPC 框架,于 2017 年对外开源,仅支持 C++ 语言。
SpringCloud:国外 Pivotal 公司 2014 年对外开源的 RPC 框架,提供了丰富的生态组件。
gRPC:Google 于 2015 年对外开源的跨语言 RPC 框架,支持多种语言。
Thrift:最初是由 Facebook 开发的内部系统跨语言的 RPC 框架,2007 年贡献给了 Apache 基金,成为Apache 开源项目之一,支持多种语言。
特性:
1、RPC框架一般使用长链接,不必每次通信都要3次握手,减少网络开销。
2、RPC框架一般都有注册中心,有丰富的监控管理。发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作协议私密,安全性较高
3、RPC 协议更简单内容更小,效率更高,服务化架构、服务化治理,RPC框架是一个强力的支撑。
目前Dubbo在企业中有两种开发思路
- 基于SOA思想
将传统单一应用拆分为web(消费者)模块和service(提供者)模块,基于Dubbo通信。

- 辅助SpringCloud架构提升效率
Dubbo基于TCP(传输层)协议,效率更高。可以替换Feign,提升高并发压力。


Dubbo入门
Dubbo的基本架构

服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于负载均衡算法,选择提供者进行调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
入门实践
1、安装Nacos(参考nocos章节)
2、安装DubboAdmin
DubboAdmin是阿里巴巴管理提供的管理控制台,可以实现服务查询,详情展示,服务测试等功能。借由DubboAdmin可以更好的帮助开发人员对服务进行管理和监控。
DubboAdmin的源代码托管在github上,可以通过命令拉取。修改配置并运行
1、下载代码: git clone https://github.com/apache/dubbo-admin.git 2、在 dubbo-admin-server/src/main/resources/application.properties中指定注册中心地址 3、构建 mvn clean package -Dmaven.test.skip=true 4、启动 mvn --projects dubbo-admin-server spring-boot:run 或者 cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar 5、访问 http://localhost:8080

3、使用Dubbo构建分布式架构,完成根据用户id查询用户

3.1 搭建服务提供者user-provider
1、创建提供者模块并引入依赖(pom.xml)
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--dubbo的起步依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> </dependencies>
2、将service,mapper,domain导入到提供者模块中
3、将UserSerivice暴露为dubbo服务
@DubboService public class UserServiceImpl implements UserService { ………… }
4、application.yml配置
server:
port: 18081
spring:
datasource:
url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: user-provider
logging:
level:
cn.itcast: debug
pattern:
dateformat: HH:mm:ss:SSS
# 配置dubbo提供者
# dubbo协议和访问端口
dubbo:
protocol:
name: dubbo
port: 20881
# 注册中心的地址
registry:
address: nacos://127.0.0.1:8848
# dubbo注解的包扫描
scan:
base-packages: cn.itcast.user.service

![]()
注:针对dubbo协议及访问端口:服务消费者调用Netty服务器的20881端口,Netty相当于Socket服务器。Tomcat相当于提供者运行启动的容器。


3.2 搭建服务消费者user-consumer
1、创建提供者模块并引入依赖
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--dubbo的起步依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> </dependencies>
2、将controller,service接口导入到提供者模块中
3、在Controller中引入dubbo服务
@RestController @RequestMapping("/user") public class UserController { //引用远程服务 @DubboReference private UserService userService;
4、application.yml配置
server:
port: 18080
spring:
application:
name: user-consumer
logging:
level:
cn.itcast: debug
pattern:
dateformat: HH:mm:ss:SSS
dubbo:
registry:
address: nacos://127.0.0.1:8848
3.3 将API接口抽取为独立模块,并且把接口有关的domain都放到这个模块中

序列化
两个机器传输数据,在RPC通信时,往往采用二进制数据格式传输Java对象,故需要对对象进行序列化处理。

dubbo 内部已经将序列化和反序列化的过程内部封装了。在定义domain类时实现Serializable接口即可。

Dubbo的高级特性
启动检查
为了保障服务的正常可用,Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常。

在正式环境这是很有必要的一项配置,可以保证整个调用链路的平稳运行。
在开发时,往往会存在没有提供者的情况。由于启动检查的原因,可能导致开发测试出现问题。
可以通过check=false关闭。

多版本
在正式系统中,为了保证系统可用性和更好的并发性,往往通过集群部署。
如果提供者代码出现重大更新。如何对提供者升级部署呢?
Dubbo提供了提供者多版本的支持,平滑处理项目功能升级部署。

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。
多版本实现
1、编写新的UserServce实现类,作为新版本代码2、在暴露服务时,指定服务版本


3、消费者引用服务时,指定引用的服务版本

超时与重试
服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
- dubbo 利用超时机制来解决这个问题(使用timeout属性配置超时时间,默认值1000,单位毫秒)。
消费者调用提供者是设置一个超时时间,等待超过该时间无响应将连接关闭。

- 若超时时间较短,当网络波动时请求就会失败,Dubbo通过重试机制避免此类问题的发生。
解决:引入重试机制,当前请求失败,会再次发送两遍请求,如都没响应,断开连接。(一共访问三次)

针对增删改涉及数据库数据情况,重试三次会导致数据出错
1、可通过@DubboReference 的retries=0关闭重试:

2、也可以修改application.yml关闭所有消费者重试

负载均衡
在集群部署时,Dubbo提供了4种负载均衡策略,帮助消费者找到最优提供者并调用
- Random :按权重随机,默认值。按权重设置随机概率。

那这样一来,第1号机器它所占的数据区间就应该是0-2,那接着,第二台机器所占的区间就应该是2-5。那第三台机器所占的区间就应该是5-10。不同服务器,不同的服务提供者,不同的服务提供者,他占用的数字区间是不一样的。
由于3号机器权重设置了5,所以它占用的数字区间是最大的。那么接下来随机的时候,它会以权重的和为基数进行随机。随机一个值,如果说落在了0-2,就去访问1号提供者。如果落在了2-5,就会访问2号提供者。如果随机的值落在了5-10,就会访问3号提供者。
Random 虽然叫做随机,但是并不是真正意义上的每个人占1/3的几率。还会跟权重进行挂钩。当然你的权重越高,随机到你的概率就会越大。
- RoundRobin :按权重轮询

将所有服务器权重相加,按权重比例轮询,如1号、2号、3号服务器权重比为2:3:5,访问10次,1号2次、2号3次、3号5次。
- LeastActive:最少活跃调用数,相同活跃数的随机。

当然,你发送过来之后,这个同时调用的数量就变成2。
- ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。

那这样,后续查询所有用户等于1的,都会分配到1号服务提供者上。
那你要查询用户等于2,都会分配到2号,如果大于等于3都会分配到3号。
可通过@DubboReference 的loadbalance进行设置。


浙公网安备 33010602011771号