1.1. 一、断路器的作用。
断路器的作用是当某个服务的某个实例异常了(服务实例挂了,反应慢等),调用这个服务的客户端就会执行后备的断路器方法。 避免整个服务不可用。
例如:在双11的时候,推荐服务反应很慢,导致查询推荐很慢。因为推荐服务不是最核心的服务,调用推荐服务的client端可以返回预留的推荐商品。从而避免整个服务卡在推荐服务上。
client端使用断路器hystrix
的时候,服务提供方实例如果一个特别慢(10秒返回),一个特别快(立即返回)。如果hystrix
调用端设置超时时间是3秒。 如果落到特别慢的服务实例也会出现断路。会执行断路的逻辑。
1.2. 二、使用hystrix。
1.2.1. 2.1、user-provider 服务端代码。
服务端就只有一个/test/add
接口。把服务注册到注册中心即可。
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/add")
public int add(int a,int b) {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("add 执行完成 。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
return a + b;
}
}
1.2.2. 2.2、客户端。
2.2.1、依赖配置。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
使用了openfeign
和hystrix
。
2.2.2、配置文件。
application.yml
配置如下:
server:
port: 9002
spring:
application:
name: user-consumer-hystrix
cloud:
loadbalancer:
retry:
# 默认就是false
enabled: false
# datasource:
# driverClassName: com.mysql.jdbc.Driver
# url: jdbc:mysql://localhost:3306/user-consumer?serverTimezone=GMT%2b8
# username: root
# password: 123456
eureka:
client:
serviceUrl:
# 注册中心的地址
defaultZone: http://localhost:9999/eureka/
instance:
preferIpAddress: true
instanceId: ${spring.cloud.client.ip-address}:${server.port}
#user-provider:
# ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
feign:
# client:
# config:
# default:
#在使用hystrix时,配置这个不能改变HTTP连接的readTimeout。
# readTimeout: 1000
hystrix:
# 开启 hystrix
enabled: true
ribbon:
# 对当前实例的最大重试次数 (包含第一次请求)
MaxAutoRetries: 0
OkToRetryOnAllOperations: false
# 切换实例的最大重试次数(如果重试失败就切换下一个服务实例),下一个服务实例的重试次数(包含第一次请求)
MaxAutoRetriesNextServer: 0
# 只有下面的2个配置才可以改变 http的ReadTimeout、ConnectTimeout
ReadTimeout: 20000
ConnectTimeout: 5000
hystrix:
command:
default:
execution:
timeout:
# 默认开启超时机制
enabled: true
isolation:
thread:
# timeoutInMilliseconds必须大于ribbon.ReadTimeout。
#如果ribbon重试多次,那timeoutInMilliseconds必须大于ribbon.ReadTimeout乘以重试次数
timeoutInMilliseconds: 60000
- 需要设置
feign.hystrix.enabled=true
让Feign支持hystrix。hystrix
使用feign
来发送请求,feign
用ribbon
做负载均衡。 需要特别注意
ribbon
的几个参数:官方文档MaxAutoRetries
重试当前实例的次数。(包含第一次请求)MaxAutoRetriesNextServer
重试下一个服务器的次数。(包含第一个实例)OkToRetryOnAllOperations
对所有操作请求都进行重试。
当访问到故障请求的时候,它会再重试访问当前实例(次数由MaxAutoRetries配置),如果不行,就换一个实例进行访问,如果还是不行,再换一次实例访问(更换实例次数由MaxAutoRetriesNextServer配置),如果依然不行,返回失败信息。MaxAutoRetries
、MaxAutoRetriesNextServer
必须设置为0,否则在做增加、修改操作时必须是幂等的。
需要注意几个超时时间。
ribbon.ReadTimeout
、ribbon.ConnectTimeout
这2个是设置HTTP的超时时间。例如:服务提供方的某个http请求需要10秒才返回,那ribbon.ReadTimeout
必须设置超过10秒。 否则会超时失败。如下图:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
这个设置hystrix的超时时间。Hystrix封装了Ribbon客户端。 timeoutInMilliseconds必须大于ribbon.ReadTimeout。如果ribbon重试多次,那timeoutInMilliseconds必须大于ribbon.ReadTimeout乘以重试次数。hystrix超时时间的计算:(1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout
。 详细查看官方文档feign.client.config.default.readTimeout
这个超时时间在hystrix这里好像失效了。设置大小都无关紧要。
springcloud官方超时重试的文档
ribbon官方重试参数设置:
https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-file-sample-clientproperties
2.2.3、启用断路器。
使用@EnableCircuitBreaker
启用断路器,使用@EnableFeignClients
启用Feign
。
@EnableCircuitBreaker
@EnableFeignClients
@SpringBootApplication
public class UserConsumerHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerHystrixApplication.class, args);
}
}
2.2.4、调用服务。
/**
*调用user-provider 服务。
*/
@FeignClient(name = "user-provider",fallback = UserProviderClientFallback.class)
public interface UserProviderClient {
// @HystrixCommand(fallbackMethod = "defaultAdd")
// 请求/test/add 接口
@GetMapping("/test/add")
int add(@RequestParam(name = "a") int a, @RequestParam(name = "b") int b);
}
/**
*UserProviderClient的断路器,后备执行逻辑。(服务降级)
*/
@Component
public class UserProviderClientFallback implements UserProviderClient{
@Override
public int add(int a, int b) {
System.out.println("UserProviderClient add 出问题了。。");
return a + b + 10000;
}
}
使用@FeignClient
注解声明了要调用name = "user-provider"
的服务,
并且调用服务user-provider
出问题之后执行的后备逻辑是UserProviderClientFallback.class
里面对应的方法。
2.2.5、测试代码。
@RestController
@RequestMapping("/test")
public class TestHystrixController {
@Autowired
private UserProviderClient userProviderClient;
@GetMapping("/hystrix/callAdd")
public int callAdd() {
return userProviderClient.add(3,8);
}
}
访问 http://localhost:9002/test/hystrix/callAdd
可以看到返回了10011
。证明执行了后备逻辑。
实际上就是user-consumer-hystrix
服务调用user-provider
服务,user-provider
要10秒才返回,hystrix
设置了3秒超时。所以执行了后备逻辑。
注意请求已经到达了user-provider
,user-provider
还是会执行完自己的add方法。
1.3. 实际使用。
在fallback函数中,可以异步发送短信通知开发人员。如果是下单失败,可以短信通知客户下单失败。
1.4. 文档。
springcloud-hystrix官方文档
官方文档:获取fallback原因
官方文档:多个bean注入报错的问题
1.5. Hystrix停止开发了。
在Hystrix官网上说了Hystrix已经停止开发了, 目前是在维护中,还能使用。替代产品有以下几个:参考博客
- Resilience4J,官方推荐。
- Alibaba Sentinel