一、分布式和微服务
1.1 什么是分布式
分布式是一种系统部署方式,即根据实际情况将项目拆分成多个不同的服务,并分散部署在不同的机器是。在分布式中,生产环境的服务器或虚拟机必定超过一台。
分布式服务顾名思义服务是分散部署在不同的机器上的,一个服务可能负责几个功能,是一种面向SOA架构的,服务之间也是通过rpc来交互或者是webservice来交互的。逻辑架构设计完后就该做物理架构设计,系统应用部署在超过一台服务器或虚拟机上,且各分开部署的部分彼此通过各种通讯协议交互信息,就可算作分布式部署。
1.2 什么是微服务
微服务是一种架构设计方式,即将项目根据实际情况拆分成多个微小的服务,小到一个服务只负责一个单一的功能。这个服务可以单独部署运行,服务间可以通过rpc来互相调用。
微服务架构:
在做架构设计的时候,先做逻辑架构,再做物理架构,当你拿到需求后,估算过最大用户量和并发量后,计算单个应用服务器能否满足需求,如果用户量只有几百人的小应用,单体应用就能搞定,即所有应用部署在一个应用服务器里,如果是很大用户量,且某些功能会被频繁访问,或者某些功能计算量很大,建议将应用拆解为多个子系统,各自负责各自功能,这就是微服务架构。
1.3 两者对比
生产环境下的微服务肯定是分布式部署的,分布式部署的应用不一定是微服务架构的,比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。
二、什么是 Java RPC
2.1 RPC 概念
RPC 全程为 remote procedure call,即远程过程调用。例如两台服务器A、B上分别部署了不同的应用,A服务器上的应用想调用B服务器上的应用提供的方法,就需要通过网络来表达调用的语义和传达调用的数据。
RPC 是一个泛化的概念,严格来说一切远程调用手段都属于 RPC 范畴,Java 中的 RPC 框架 有 RMI、Hessian、Dubbo 等
2.2 基本原理图
2.3 RPC 框架性能
RPC 框架的优劣主要取决于:
- 通信效率:是否能快速的在不同服务之间建立起连接
- 序列化与反序列化效率:序列化和反序列化机制是否快速
三、Dubbo 学习
3.1 Dubbo 简介
Apache Dubbo 是一款高性能的 Java RPC 框架,可以和 Spring 框架无缝集成。
Dubbo 提供了三大核心能力:
- 面向接口的远程方法调用
- 智能容错和负载均衡
- 服务自动注册和发现
3.2 Dubbo 架构图
虚线为异步调用,实线为同步调用
蓝色虚线:在启动时未完成的功能
红色线条:在程序运行过程中执行的功能
节点角色说明:
节点 | 角色名称 |
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的消费提供方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
3.3 服务注册中心 Zookeeper
3.3.1 什么是注册中心
消费者通过注册中心来调用服务提供方,消费者和服务提供者均要在注册中心进行注册,注册中心能够监控到服务提供方是否在线,以及实现负载均衡。
3.3.2 Zookeeper 简介
Zookeeper 是 Apache Hadoop 的子项目,是一个树形的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生成环境。
3.3.3 Zookeeper 结构说明
流程说明:
- 服务提供者(Provicer)启动时,向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
- 服务消费者(Consumer)启动时,订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
- 监控中心(Monitor)启动时,订阅 /dubbo/com.foo.BarService 目录下所有的提供者和消费者 URL 地址
3.3.4 安装 Zookeeper
百度网盘:
链接:https://pan.baidu.com/s/1CL1CYr2-Eb4ZOX-fe4WFRg 提取码:13y3
官网下载地址:
http://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/
# 解压压缩包
tar -zxvf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 zookeeper
# 创建data目录
cd zookeeper
mkdir data
# 修改配置文件
cd conf
mv zoo_sample.cfg zoo.cfg
# 修改 zoo.cfg 文件
dataDir=/usr/local/lincya/zookeeper/data
3.3.4 Zookeeper 使用
# 启动 Zookeeper
./zkServer.sh start
# 停止服务命令
./zkServer.sh stop
# 查看服务状态
./zkServer.sh status
3.3.5 Zookeeper 客户端使用
# 进入客户端
sh zkCli.sh
# 查看节点
ls /
# 获取某个节点数据
get /dubbo
# 创建节点
create dubbo 123456
3.3.6 Zookeeper 可视化界面
GitHub 项目地址:
https://github.com/apache/dubbo-admin
使用教程:
访问结果:
四、Dubbo 搭建基于 xml 的实例
4.1 提供方搭建
4.1.1 引入 maven 依赖
<dependencies>
<dependency>
<groupId>com.tom</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 引入操作zookeeper的客户端 -->
<!-- dubbo 2.6 以前使用 zkclient -->
<!-- <dependency>-->
<!-- <groupId>org.101tec</groupId>-->
<!-- <artifactId>zkclient</artifactId>-->
<!-- <version>0.10</version>-->
<!-- </dependency>-->
<!-- dubbo 2.6 及以后使用 curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies>
4.1.2 增加注解
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="user-service-provider"/>
<!-- 指定注册中心地址 -->
<dubbo:registry address="zookeeper://www.greattom.xyz:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl"/>
<!-- 和本地bean一样实现服务 -->
<bean id="userServiceImpl" class="com.tom.service.impl.UserServiceImpl"/>
<!-- 设置请求超时时间 -->
<dubbo:provider timeout="5000"></dubbo:provider>
<!-- 自动发现监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
</beans>
4.1.3 修改启动类
使用 ClassPathXmlApplicationContext 加载配置文件
public class ProviderApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
ioc.start();
System.in.read();
}
}
4.1.4 编写服务代码
import com.tom.bean.UserAddress;
import com.tom.service.UserService;
import java.util.Arrays;
import java.util.List;
public class UserServiceImpl implements UserService {
public List<UserAddress> getUserAddressList(String userId) {
UserAddress address1 = new UserAddress(1, "北京市", "1", "小王", "18030145000", "1");
UserAddress address2 = new UserAddress(2, "杭州市", "2", "小北", "18030145999", "2");
return Arrays.asList(address1, address2);
}
}
4.2 服务方搭建
4.2.1 引入 maven 依赖
与提供方相同
4.2.2 增加注解
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:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.tom.service.impl"></context:component-scan>
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="order-service-consumer"/>
<!-- 使用注册中心 -->
<dubbo:registry address="zookeeper://www.greattom.xyz:2181"/>
<!-- 生成远程服务代理 -->
<dubbo:reference interface="com.tom.service.UserService" id="userService"/>
<!-- 自动发现监控中心 -->
<dubbo:monitor protocol="registry"></dubbo:monitor>
<!-- <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>-->
</beans>
4.2.3 修改启动类
public class ConsumerApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
OrderService orderService = applicationContext.getBean(OrderService.class);
orderService.initOrder("1");
System.out.println("调用完成...");
System.in.read();
}
}
4.2.4 编写服务代码
import com.tom.bean.UserAddress;
import com.tom.service.OrderService;
import com.tom.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
UserService userService;
public void initOrder(String userId) {
System.out.println("用户ID: " + userId);
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress item : addressList) {
System.out.println(item.getUserAddress());
}
}
}
五、Dubbo 搭建基于注解的实例
Github项目地址:https://github.com/IDLC1/dubboDemos
项目相关依赖版本:
- jdk: 1.8
- dubbo: 2.7.7
- zookeeper: 3.6.1
- curator: 5.0.0
5.1 提供者搭建
5.1.1 引入 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.tom</groupId>
<artifactId>boot-dubbo-common-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.version}</version>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
</dependencies>
5.1.2 修改配置文件
dubbo.application.name=dubbo-order-provicder
# 指定 zookeeper 注册,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
# 指定要扫描的包
dubbo.scan.base-packages=com.tom.bootdubboorderprovider.service
# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry
5.1.3 修改启动类
@SpringBootApplication
@EnableDubbo
public class BootDubboOrderProviderApplication {
public static void main(String[] args) {
SpringApplication.run(BootDubboOrderProviderApplication.class, args);
}
}
5.1.4 实现类中使用
@DubboService
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
UserAddress address1 = new UserAddress(1, "北京市", "1", "小王", "18030145000", "1");
UserAddress address2 = new UserAddress(2, "杭州市", "2", "小北", "18030145999", "2");
return Arrays.asList(address1, address2);
}
}
5.2 消费者搭建
5.2.1 引入 maven 依赖
依赖于提供者相同
5.2.2 修改配置文件
server.port=8084
dubbo.application.name=dubbo-user-consumer
# 指定 zookeeper 注册,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator
# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry
5.2.3 修改启动类
@SpringBootApplication
@EnableDubbo
public class BootDubboUserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(BootDubboUserConsumerApplication.class, args);
}
}
5.2.4 实现类中使用
使用 @Reference 来调用 dubbo 上注册的提供者
@Service
public class OrderServiceImpl implements OrderService {
@DubboReference
UserService userService;
@Override
public List<UserAddress> initOrder(String userId) {
System.out.println("用户ID: " + userId);
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress item : addressList) {
System.out.println(item.getUserAddress());
}
return addressList;
}
@Override
public String orderTest(String id) {
return "order test!";
}
}
5.3 Dubbo 配置解析
# 指定 dubbo 在 zookeeper 上注册的服务名
dubbo.application.name=dubbo-user-consumer
# 指定 zookeeper 注册中心,使用 curator 客户端
dubbo.registry.address=zookeeper://www.greattom.xyz:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.client=curator
# 设置 dubbo 在启动时不检查 zookeeper 上是否已经注册了依赖
# 用于不同服务间的互相调用
dubbo.consumer.check=false
# 协议方式和端口,用于其他服务调用。
# 不同的服务端口不能相同
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
# 要暴露的包路径
dubbo.scan.base-packages=com.tom.bootdubbouserconsumer
# dubbo监控设置为自动获取
dubbo.monitor.protocol=registry
六、Dubbo 详细配置
官网文档:http://dubbo.apache.org/zh-cn/docs/user/demos/preflight-check.html
6.1 配置覆盖关系
6.1.1 配置优先级
- 精确优先:方法级优先,接口次之,全局配置再次之
- 消费方优先:若级别一致,则消费方优先,提供方次之
6.1.2 在Provider上尽量多配置Consumer属性
- 服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数,等等
- 在 provider 配置后,consumer 不配置则会使用 provider 的配置值,即 provider 配置可以作为 consumer 的缺省值。否则,consumer 会使用 consumer 端的全局设置,这对于 provider 不可控的,并且往往是不合理的
6.2 启动时检查
6.3 超时时间配置
根据实际情况,修改 dubbo 访问其他提供者的接口超时时间。Dubbo 默认超时时间为 1 秒,在实际情况中 1 秒对于服务的请求速度要求很高,故应该根据实际情况进行统一或针对性修改
统一修改和针对性修改可以同时存在,且优先级:针对性修改 > 统一修改
6.3.1 统一修改
在 springboot 配置文件中增加:
dubbo.provider.timeout=3000
6.3.2 针对性修改
@DubboService(timeout = 5000)
@Service
public class OrderServiceImpl implements OrderService {
@DubboReference(timeout = 3000)
UserService userService;
@Override
public List<UserAddress> initOrder(String userId) throws InterruptedException {
System.out.println("用户ID: " + userId);
List<UserAddress> addressList = userService.getUserAddressList(userId);
for (UserAddress item : addressList) {
System.out.println(item.getUserAddress());
}
return addressList;
}
}
6.3.3 xml 修改
<dubbo:provider timeout="5000"></dubbo:provider>
6.4 重试次数配置
可以根据实际情况设置请求的重试次数,默认为 3 次。为实际配置值 N + 1
方法分类:
- 幂等方法:无论多少次,只要请求数据不变,则响应结果最终都是同一个效果,如查询、删除、修改
- 非幂等方法:每次运行都会产生新的效果,如数据库新增
设置区别:
- 幂等方法:设置重试次数
- 非幂等方法:不能设置重试次数,设置为0
6.4.2 xml 配置
统一配置:
<dubbo:provider timeout="2000" retries="5"></dubbo:provider>
针对方法配置:
<!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl">
<dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>
6.5 灰度发布
6.5.1 概念
概念:
dubbo多版本控制: http://dubbo.apache.org/zh-cn/docs/user/demos/multi-versions.html
6.5.2 适应场景
- 当接口存在不兼容的升级时,要让一部分用户用新版本,又要支持老版本接口的使用,可以使用dubbo多版本控制
- 当服务要更新时,无法确保线上服务更新正常,需要先进行测试,之后逐步将用户流量指引向新版本
6.5.3 示例代码
提供方:
<!-- 声明需要暴露的服务接口 ref指向服务真正的实现对象 -->
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl01" version="1.0.0">
<dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>
<dubbo:service interface="com.tom.service.UserService" ref="userServiceImpl02" version="2.0.0">
<dubbo:method name="getUserAddressList" timeout="2000" retries="8"></dubbo:method>
</dubbo:service>
<!-- 和本地bean一样实现服务 -->
<bean id="userServiceImpl01" class="com.tom.service.impl.UserServiceImpl"/>
<bean id="userServiceImpl02" class="com.tom.service.impl.UserServiceImpl2"/>
调用方:
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference interface="com.tom.service.UserService" id="userService" version="2.0.0"/>
6.6 本地存根
6.6.1 概念
远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub [1],然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。
七、Springboot 整合 Dubbo 的三种方式
7.1 描述
SpringBoot 整合 Dubbo 的方式有:
- 注解配置方式(常用):在 springboot 配置文件中配置相关内容,使用 @Service 和 @Reference 注解实现功能
- xml配置方式(常用):使用 xml 配置文件,使用 @ImportResource 导入生效
- 注解Api方式(知道):创建dubbo配置文件,依次注册 dubbo 组件到项目中
7.2 三种方式对比
| 注解配置方式 | xml配置方式 | 注解API方式 |
配置方式 | 导入 dubbo-starter,在配置文件中进行配置,使用@Service暴露服务,使用@Reference引用服务 | 首先导入dubbo-starter,然后使用 @ImportResource 加载 xml 配置文件 | 创建统一的dubbo配置文件,将dubbo的每一个组件手动注入到springboot项目中 |
优点 | 配置快速方便 | 支持精确配置 | 支持精确配置 |
缺点 | 不支持精确配置,如针对 method 进行配置 | | 配置繁琐,不常用 |
八、常见的高可用场景
高可用即通过设计,减少系统不能提供服务的时间
Dubbo 与 Zookeeper 的高可用有:
- 监控中心宕机后不影响使用,只是丢失部分采样数据
- 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询, 但无法注册新服务
- 注册中心对等集群,任意一台宕机后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯,即 dubbo 直连
- 服务提供者无状态,任意一台宕掉后,不影响使用
- 服务提供者全部宕掉后,服务消费者将无法使用, 并无限次重试等待服务提供者恢复
8.1 Zookeeper 宕机与 dubbo 直连
8.1.1 本地缓存
当消费者调用过提供者的方法后,消费者会在本地存储提供者的地址以及方法信息,故当 Zookeeper 宕机后消费者依旧可以消费提供者提供的服务
8.1.2 dubbo 直连
需要保证 provider 服务正常运行中
修改 consumer 配置,关闭 zookeeper 连接配置
进入管理界面查看提供者的地址信息
修改 consumer 的引用
可以正常调用了
8.2 Dubbo 负载均衡
8.2.1 四种负载均衡策略
Dubbo内置了4种负载均衡策略:
- RandomLoadBalance:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
- RoundRobinLoadBalance:轮询负载均衡。轮询选择一个。
- LeastActiveLoadBalance:最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
- ConsistentHashLoadBalance:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。
8.2.2 随机负载均衡(或基于权重)
随机负载均衡即随机选择一个节点进行请求,接下来主要介绍基于权重的随机负载均衡
例如 orderService 是一个消费者,userService 是提供者,根据权重的不同,大致会有1/6的请求来带A服务,3/6的请求会来到B服务,2/6的请求会来到C服务,并不是严格遵守比例,不能保证顺序调用,只能够保证大概一致
8.2.3 轮询负载均衡(或基于权重)
轮询负载均衡即在所有节点中间循环发送请求,接下来主要介绍基于权重的轮询负载均衡
例如 orderService 是一个消费者,userService 是提供者,根据权重的不同,在一次完整的轮询((100+300+200)/100 = 6次)中,A服务一定只会被轮询到一次,B服务被轮询到3次,C服务轮询到2次
8.2.4 最少活跃数负载均衡
最少活跃数通俗来说就是将请求指向处理速度更快的提供者节点,让请求速度更慢的节点收到更少的请求
例如 orderService 是一个消费者,userService 是提供者,根据响应时间的不同,请求会更多地指向A节点,B节点次之,C节点最少
8.2.5 一致性Hash负载均衡
一致性Hash是指将调用方法相同、参数相同的请求发送到同一个提供者节点中
例如 orderService 是一个消费者,userService 是提供者,则无论请求数量多少,id为1的请求永远发送到A服务,id为2的请求永远发送到B服务,id为3的请求永远发送到C服务。
8.3 负载均衡配置
8.3.1 设置负载均衡方法
8.3.2 设置权重
8.4 服务降级
8.4.1 概念
服务降级即当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
我们可以通过服务降级功能临时屏蔽某个出错的非关键业务,并定义降级后的返回策略
8.5 集群容错
8.5.1 概念和模式
在集群调用失败时,Dubbo 提供了多种容错方案,默认为 failover 重试
Failfast Cluster(默认)
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2"
来设置最大并行数。
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
8.5.2 修改方式
<dubbo:reference cluster="failsafe" />
8.5 集群容错结合 Hyxtrix
8.5.1 概念
Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix 具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能
8.5.2 使用
消费者和提供者均引入依赖:
使用 EditStarters 插件,在 setting -> plugin 中搜索并安装
按住 Alt + Insert
使用默认地址
自动添加
修改消费者和提供者的启动类:
提供者方法修改:
消费者方法修改: