Hystrix实现服务降级,服务熔断介绍
1 Hystrix简介
1.1 介绍
- Hystrix是一个用于处理分布式系统的延迟和容错的开源库
- Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性
- “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选相应(FallBack),而不是长时间的等待或抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
1.2 功能
- 服务降级
- 服务熔断
- 接近实时的监控
1.3 资料
2 Hystrix重要概念
2.1 服务降级(fallback)
- 如果当前对方服务不可用,给出一个解决方法来
- 类似我们的if-else判断语句
- 举例:”服务器繁忙,请稍后再试!”,不让客户端等待并立刻返回一个友好提示(fallback)
- 发生降级的情况;
- (1)程序运行异常
- (2)超时
- (3)服务熔断触发服务降级
- (4)线程池 / 信号量打满导致服务降级
2.2 服务熔断(break)
- 类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示
- 类似保险丝
2.3 服务限流(flowlimit)
- 秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
3 Hystrix使用
3.1 服务端简单搭建环境
- (1) 创建
cloud-provider-hystrix-payment8001
项目
(2)依赖导入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>(3)yaml配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16server:
port: 8001 #端口
spring:
application:
name: cloud-provider-hystrix-payment #服务名称
eureka:
instance:
instance-id: hystrix-payment8001 # eureka中服务名称
prefer-ip-address: true # 访问路径是否可以显示IP地址
client:
register-with-eureka: true # 是否注册进eureka服务端
fetch-registry: true # 是否从eureka server从获取已有的注册信息,默认true。单节点无所谓,集群的话需要
service-url:
defaultZone: http://localhost:7001/eureka
- (4)主启动类
1
2
3
4
5
6
7
//表示此服务器是eureka client
public class PaymentHystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixMain8001.class, args);
}
}
- (5)Serviec层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class PaymentService {
//模拟服务正常
public String paymentInfo_OK(Integer id) {
return "线程池:" + Thread.currentThread().getName() + "\n-- OK --\nid:" + id;
}
//模拟服务异常:超时
public String paymentInfo_Timeout(Integer id) {
try { //沉睡3秒
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "\n-- Timeout --\nid:" + id;
}
}
- (6)Controller层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PaymentController {
PaymentService paymentService;
public String getOKInfo( Integer id){
return paymentService.paymentInfo_OK(id);
}
public String getTimeInfo( Integer id){
return paymentService.paymentInfo_Timeout(id);
}
}
3.2 客户端简单环境搭建
- (1)创建项目
cloud-consumer-openfeign-hystrix-order
(2)依赖引入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- openfeign:内整合了ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>(3)yaml配置
1
2
3
4
5
6
7
8
9
10spring:
application:
name: cloud-consumer-openfeign-hystrix-order
eureka:
client:
register-with-eureka: true # 是否注册进eureka服务端
fetch-registry: true # 是否从eureka server从获取已有的注册信息,默认true。单节点无所谓,集群的话需要
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka/(4)主启动类
1
2
3
4
5
6
7
8
//表示自己是OpenFeign的客户端
public class OrderOpenFeignHystrixMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderOpenFeignHystrixMain80.class, args);
}
}
- (5)feign接口
1
2
3
4
5
6
7
8
9
10
//对应服务器的名词
public interface PaymentFeignClient {
public String getOKInfo( Integer id);
public String getTimeInfo( Integer id);
}
- (6)Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class OrderFeignController {
PaymentFeignClient paymentFeignClient;
public String getOKInfo( Integer id){
return paymentFeignClient.getOKInfo(id);
}
public String getTimeInfo( Integer id){
return paymentFeignClient.getTimeInfo(id);
}
}
3.2 服务降级配置
- (1)解决服务端超时
- 服务端设置自身调用超时时间峰值,峰值内正常运行
- 超过峰值,需要有兜底的方法进行处理,作为服务降级fallback
1 | //模拟服务异常:超时 |
1 | //主启动类 |
- (2)客户端配置
1 |
|
1 | //主启动类 |
4 问题出现与解决
4.1 问题
- (1)如果每一个业务方法都要有一个服务降级的方法,会导致代码膨胀
- (2)业务方法与服务降级方法写在了一起,会十分的不舒服,不适合维护
4.2 代码膨胀解决
- 在类头添加注解
@DefaultProperties(defaultFallback = "")
- 会自动对添加了
@HystrixCommand
的注解默认使用此服务降级方法
1 |
|
4.3 业务方法降级方法分离
- 我们可以通过使用feign对hystrix方法的支持,来实现分离
- 在feign接口头上的注解新增属性:
@FeignClient(value = "", fallback = "")
,参数为一个类
1 | //记得能够被扫描到 |
1 |
|
1 | feign: |
5 服务熔断
5.1 服务熔断理论
- closed –> open:达到服务器极限,开启熔断
- open –> half open:一段时间后,尝试取消熔断
- half open –> closed:没有异常,关闭熔断
5.2 配置服务熔断
官网参数详情:https://github.com/Netflix/Hystrix/wiki/Configuration
或者SpringBoot项目搜
HystrixCommandProperties.class
查看可配置参数以下案例在服务端进行配置
1 | //paymentService |
- 测试:自己配一个对应的Controller接口,用负数进行错误请求达到6次以上,再用正数进行正确请求,会发现无法进行正确请求,因为服务器处于熔断状态。10秒后再进行请求,发现可以正常请求,服务器处理熔断关闭阶段
6 服务监控HystrixDashboard
6.1 介绍
- Hystrix提供了准实时的调用监控(Hystrix Dashborad)。Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户。
6.2 搭建HystrixDashboard
- (1)创建一个新工程
cloud-provider-hystrix-dashboard
- (2)依赖引入
1
2
3
4
5
6
7
8
9
10<!-- hystrix-dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- (3)yaml配置文件
1
2server:
port: 9001
- (4)主启动类
1
2
3
4
5
6
7
//开启HystrixDashboard
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class, args);
}
}
- (5)测试:输入网址:http://localhost:9001/hystrix
6.3 服务监控测试
以下例子在
cloud-provider-hystrix-payment8001
来实现(1)引入依赖
1
2
3
4
5<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- (2)修改yaml配置文件
1
2
3
4
5management:
endpoints:
web:
exposure:
include: 'hystrix.stream' #暴露hystrix监控端点
- (3)启动服务器并返回hystrix dashboard