Dubbo源码学习
官网链接
http://dubbo.apache.org/zh-cn/docs/dev/design.html
分布式理论概念
RPC
-
什么是RPC
英文全称是Remote Procedure Call,意指远程过程调用,是一种进程间通信方式,是一种技术思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,不需要编写显式调用代码
-
基本原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eUu36BmX-1582618693283)(./RPC基本原理.png)]
-
性能指标
- 通信效率
- 序列化与反序列化效率
-
RPC框架
Apache——dubbo
谷歌——gRPC
Facebook——Thrift
阿里——HSF(High Speed Service Framework)
Dubbo核心概念
简介
高性能、轻量级的开源Java RPC框架
-
官网
http://dubbo.apache.org -
三大核心能力
-
面向接口的远程方法调用
-
智能容错和负载均衡
-
服务自动注册和发现
-
设计架构
-
例图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jV3JmOFY-1582618693285)(./Dubbox服务框架.png)]
-
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推 送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用, 如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计 数据到监控中心。
注册中心ZooKeeper(官方推荐)
- ZooKeeper配置
- 添加一个zoo.cfg配置文件
```sh
$ZOOKEEPER/conf
mv zoo_sample.cfg zoo.cfg
```
2. 修改配置文件(zoo.cfg)
```sh
dataDir=/itcast/zookeeper-3.4.5/data
server.5=itcast05:2888:3888
server.6=itcast06:2888:3888
server.7=itcast07:2888:3888
```
3. 在(dataDir=/itcast/zookeeper-3.4.5/data)创建一个myid文件,里面内容是server.N中的N(server.2里面内容为2)
```sh
echo "5" > myid
```
4. 将配置好的zk拷贝到其他节点
```sh
scp -r /itcast/zookeeper-3.4.5/ itcast06:/itcast/
scp -r /itcast/zookeeper-3.4.5/ itcast07:/itcast/
```
5. 注意:在其他节点上一定要修改myid的内容
```sh
# 在itcast06应该讲myid的内容改为6
echo "6" > myid
# 在itcast07应该讲myid的内容改为7
echo "7" > myid
```
Dubbo环境搭建
安装VMware
安装CentOS7
安装ZooKeeper(Linux环境)
- 官网下载地址
https://archive.apache.org/dist/zookeeper/
安装Dubbo(Linux环境)
Dubbo项目搭建
参考官网
http://dubbo.apache.org/zh-cn/docs/user/quick-start.html
引入Dubbo依赖
-
依赖配置
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency>
引入操作ZooKeeper客户端依赖
-
注意事项
dubbo 2.6以前版本引入zkclient操作zookeeper
dubbo 2.6及以后版本引入curator操作zookeeper -
依赖配置
<!-- 注册中心使用zookeeper引入操作zookeeper的客户端 --> <dependency> <groupId>com.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency>
服务提供者配置文件
-
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"> <!-- 1.指定服务名称:提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-app" /> <!-- 2.指定注册中心配置:使用zookeeper注册中心暴露服务地址 --> <!-- 单机配置 --> <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" /> <!-- 集群配置 --> <!-- <dubbo:registry address="zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181" /> --> <!-- 3.指定通信规则:用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 4.指定暴露接口名称:声明需要暴露的服务接口 --> <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" /> <!-- 5.指定暴露接口实现类:和本地bean一样实现服务 --> <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl" /> </beans>
服务消费者配置文件
-
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="consumer-of-helloworld-app" /> <!-- 使用zookeeper注册中心暴露发现服务地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" /> </beans>
Dubbo整合SpringBoot
注意事项
服务提供者和消费者都要引入接口依赖
引入SpringBoot整合Dubbo的依赖
-
依赖配置
<!-- Dubbo Spring Boot Starter --> <!-- <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.5</version> </dependency> --> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.2.1</version> </dependency>
服务提供者配置文件
-
application.properties
dubbo.application.name=hello-world-app dubbo.application.registry=127.0.0.1:2181 dubbo.application.protocol=zookeeper dubbo.protocol.name=dubbo dubbo.protocol.port=20880 dubbo.monitor.protocol=registry
-
注意事项
- 在需要暴露的接口实现类上添加@Service注解(是dubbo下的,而不是spring下的)
- 在启动类上添加@EnableDubbo注解,开启基于注解的dubbo
服务消费者配置文件
-
application.properties
dubbo.application.name=boot-order-service-consumer dubbo.registry.address=zookeeper://127.0.0.1:2181 dubbo.monitor.protocol=registry
-
注意事项
- 在需要引用的接口实现类中引用的接口上面使用@Reference注解,替代@Autowired
- 在启动类上添加@EnableDubbo注解,开启基于注解的dubbo
Dubbo监控中心
dubbo-admin
-
简介
图形化的服务管理页面;安装时需要指定注册中心地址,即可从注册中心中获取到所有的提供者、消费者进行配置管理
dubbo-monitor-simple
-
简介
简单的监控中心
-
服务提供者和服务消费者都需要配置监控中心
<!-- 从注册中心发现监控中心地址,否则直连监控中心 --> <dubbo:monitor protocol="registry"></dubbo:monitor> <!-- 指定监控中心地址 --> <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>
Dubbo基础配置
配置来源
-
优先级从上往下依次降低
-
JVM System Properties,-D参数
-
Externalized Configuration,外部化配置
-
ServiceConfig、ReferenceConfig等编程接口采集的配置
-
本地配置文件dubbo.properties
-
启动时检查
-
作用
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check=“true”
-
通过spring配置文件为例
- 关闭某个服务的启动时检查 (没有提供者时报错):
<dubbo:reference interface="com.foo.BarService" check="false" />
- 关闭所有服务的启动时检查 (没有提供者时报错):
<dubbo:consumer check="false" />
- 关闭注册中心启动时检查 (注册订阅失败时报错):
<dubbo:registry check="false" />
配置属性
-
配置覆盖关系
以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:
方法级优先,接口级次之,全局配置再次之。
如果级别一样,则消费方优先,提供方次之。 -
timeout属性
默认超时时间1000ms
<dubbo:reference timeout="1000"></dubbo:reference>
-
retries属性
重试次数不包含第一次调用
幂等:设置重试次数(查询、修改、删除)
非幂等:不能设置重试次数(新增)<dubbo:reference timeout="1000" retries="3"></dubbo:reference>
-
version多版本属性
<dubbo:reference interface="com.atguigu.gmall.service.UserService" id="userService" timeout="5000" retries="3" version="1.0.0"></dubbo:reference>
-
本地存根
本地存根既可以在消费者本地创建也可以在服务者本地创建
消费者:dubbo:reference</dubbo:reference>
<dubbo:reference interface="com.atguigu.gmall.service.UserService" id="userService" timeout="5000" retries="3" version="1.0.0" stub=""></dubbo:reference>
服务者:dubbo:service</dubbo:service>
<dubbo:service interface="com.foo.BarService" stub="true" />
Dubbo配置与SpringBoot整合三种方式
导入dubbo-starter
在application.properties配置属性,使用@Service(暴露服务),使用@Reference(引用服务)
保留dubbo.xml配置文件
-
在启动类上使用@ImportResource(locations=“classpath:provider.xml”)导入配置文件,替代@EnableDubbo
-
取消@Service注解
使用注解API方式
-
写一个配置类,使用@Configuration注解,将每一个组件写在配置类中,并在类中方法上添加@Bean注解
-
在启动类上使用@DubboComponentScan(scanBasePackages=“com.atguigu.gmall”)或者@EnableDubbo(scanBasePackages=“com.atguigu.gmall”)注解,从而让dubbo扫描组件
高可用
现象
zookeeper注册中心宕机,还可以消费dubbo暴露的服务
原因分析
-
注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
-
数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
-
dubbo直连配置
在@Reference(url=“127.0.0.1:20882”)
集群下Dubbo负载均衡配置
负载均衡策略
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为Random随机调用
-
Random LoadBalance
随机,按权重设置随机概率
-
RoundRobin LoadBalance
轮询,按公约后的权重设置轮询比率
-
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差
-
ConsistentHash LoadBalance
一致性Hash,相同参数的请求总是发到同一提供者
相关实体类
-
LoadBalance中注解
@SPI(RandomLoadBalance.NAME)
-
AbstractLoadBalance抽象类
RandomLoadBalance
RoundRobinLoadBalance
LeastActiveLoadBalance
ConsistentHashLoadBalance
配置示例
配置文件
-
服务端服务级别
<dubbo:service interface="..." loadbalance="roundrobin" />
-
客户端服务级别
<dubbo:reference interface="..." loadbalance="roundrobin" />
-
服务端方法级别
<dubbo:service interface="..."> <dubbo:method name="..." loadbalance="roundrobin"> </dubbo:service>
-
客户端方法级别
<dubbo:reference interface="..."> <dubbo:method name="..." loadbalance="roundrobin"> </dubbo:reference>
注解样例
-
客户端方法级别
@Reference(loadbalance=“roundrobin”)
服务降级
概念
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作
实现方式
-
mock=force(return+null)——屏蔽
表示消费方对该服务的方法调用都直接返回null值,不发起远程调用那个。用来屏蔽不重要服务不可用时对调用方的影响 -
mock=fail(return+null)——容错
表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响
集群容错
在集群调用失败是,Dubbo提供了多种容错方案,缺省为failover重试,需要配置重试次数
-
Failover Cluster
失败自动切换,当出现失败,重试其他服务器。通常用于读操作,但重试会带来更长延迟。可通过retries="2"来设置重试次数(不含第一次)
-
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录
-
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作
-
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数 -
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息
集群模式配置
按照以下示例在服务提供方和消费方配置集群模式
<dubbo:service cluster="failsafe" />
<dubbo:reference cluster="failsafe" />
整合hystrix
概念
Hystrix旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能
SpringBoot+Hystrix
-
pom.xml中添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>1.4.4.RELEASE</version> </dependency>
-
在Application类上增加@EnableHystrix来启用hystrix starter
@SpringBootApplication @EnableHystrix public class ProviderApplication{ }
-
在方法上添加注解@HystrixCommand配置,经过Hystrix代理
//调用方 @HystrixCommand(fallbackMethod="") //提供方 @HystrixCommand
dubbo原理
RPC原理
netty通信原理
Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。它极大地简化地简化了TCP和UDP套接字服务器等网络编程
-
BIO(Blocking IO)
-
NIO(Non-Blocking IO)
李贺飞老师-NIO视频Selector选择器
可以翻译为多路复用器
Connnect(连接就绪)、Accept(接受就绪)、Read(读就绪)、Writre(写就绪)
Nettty基本原理
Boss NioEvenLoopGroup——负责监听来自于端口所有连接准备就绪时间
Worker NioEvenLoopGroup——接收准备就绪的连接准备做的工作
dubbo原理
dubbo原理-框架设计
dubbo原理-启动解析、加载配置信息
-
解析器总接口
BeanDefinitionParser
dubbo原理-服务暴露
-
Protocol是用来暴露执行器Invoker
- Dubbo协议的Protocol对应DubboExporter
- Registry的Protocol对应RegistryExporter
-
源码解析
// 以url地址为键,以url+服务方法(url地址的服务) public static ConcurrentHashMap<String, Set<ProvidreInvokerWrapper>> providerInvokerWrapper
dubbo原理-服务引用
-
源码解析
//获取连接客户端 connect/getClients() //远程地址信息 ProviderConsumerRegTable.registerConsumer