Table of Contents
1.Hystrix 介绍
2.pom.xml中添加依赖
3.服务降级
降级在提供者(provider-hystrix-payment8007)
降级在消费者(consumer-feign-hystrix-order80)
全局服务降级
4.服务熔断
5.工作流程
6.hystrix dashboard监控
7.hystrix + turbine 集群聚合监控
https://github.com/Netflix/Hystrix/wiki
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。
在springcloud中断路器组件就是Hystrix。Hystrix也是Netflix套件的一部分。他的功能是,当对某个服务的调用在一定的时间内(默认10s),有超过一定次数(默认20次)并且失败率超过一定值(默认50%),该服务的断路器会打开。返回一个由开发者设定的fallback。
Hystrix被设计的目标是:
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
三种情况:
访问超时
运行错误
宕机
@EnableCircuitBreaker
@EnableEurekaClient
@SpringBootApplication
public class Payment8007 {
public static void main(String[] args) {
SpringApplication.run(Payment8007.class,args);
}
}
@Service
public class PaymentServiceImpl implements PaymentService {
/**
* 访问超时
*
* @param id
* @return
*/
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
public String paymentInfo_TimeOut(Integer id) {
int timeNumber = 5;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (Exception e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentinfo_Timeout,id:" + id + "\t" + "耗时(秒)" + timeNumber;
}
private String paymentInfo_TimeOutHandler(Integer id) {
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOutHandler,id:" + id + "\t";
}
}
application.yml
feign:
hystrix:
enabled: true
@EnableHystrix
@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class OrderFeignHystrix80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignHystrix80.class,args);
}
}
@Slf4j
@RestController
@RequestMapping("/order/payment")
public class OrderPaymentController {
@Autowired
private PaymentFeignService paymentFeignService;
@GetMapping("paymentInfo_TimeOut/{id}")
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
public String paymentInfo_TimeOut(@PathVariable Integer id) {
return paymentFeignService.paymentInfo_TimeOut(id);
}
private String paymentInfo_TimeOutHandler(Integer id) {
return "OrderPayment 线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOutHandler,id:" + id + "\t";
}
}
或者
@Primary
@FeignClient(value = "PAYMENT-SERVICE2",fallback = PaymentFeignService2.PaymentFeignService2FallBack.class)//模拟不存在的服务,宕机
public interface PaymentFeignService2 {
@GetMapping("payment/paymentInfo_TimeOut/{id}")
String paymentInfo_TimeOut(@PathVariable("id") Integer id);
@Component
class PaymentFeignService2FallBack implements PaymentFeignService2{
@Override
public String paymentInfo_TimeOut(Integer id) {
return "PAYMENT-SERVICE2 宕机";
}
}
}
问题:
1、每个方法有一个对应的处理方法,代码膨胀。
2、处理方法和主业务逻辑混合在一起
解决方案:
@DefaultProperties(defaultFallback="")
类上加上注解:
默认全局处理方法
@HystrixCommand//不加属性代表使用默认的全局处理方法。
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
@Slf4j
@RestController
@RequestMapping("/order/payment")
public class OrderPaymentController {
@Autowired
private PaymentFeignService paymentFeignService;
@GetMapping("paymentInfo_TimeOut/{id}")
// @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
// })
@HystrixCommand
public String paymentInfo_TimeOut(@PathVariable Integer id) {
return paymentFeignService.paymentInfo_TimeOut(id);
}
private String paymentInfo_TimeOutHandler(Integer id) {
return "OrderPayment 线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOutHandler,id:" + id + "\t";
}
private String payment_Global_FallbackMethod() {
return "全局 线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOutHandler";
}
类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示:
服务的降级->进而熔断->恢复调用链路
熔断机制概述:
熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现. Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解是@HystrixCommand.
//====服务熔断
/**
* 在10秒窗口期中10次请求有6次是请求失败的,断路器将起作用
*
* @param id
* @return
*/
@HystrixCommand(
fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),// 时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")// 失败率达到多少后跳闸
}
)
public String paymentCircuitBreaker(Integer id) {
if (id < 0) {
throw new RuntimeException("*****id不能是负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
private String paymentCircuitBreaker_fallback(Integer id) {
String serialNumber = IdUtil.simpleUUID();
return "id 不能负数,请稍后重试,o(╥﹏╥)o id:" + id+" 流水号:" + serialNumber;
}
Hystrix断路器常用的三个重要指标参数
1、circuitBreaker.requestVolumeThreshold
断路器的窗口期内触发断路的请求阈值,默认为20。换句话说,假如某个窗口期内的请求总数都不到该配置值,那么断路器连发生的资格都没有。断路器在该窗口期内将不会被打开。
2、circuitBreaker.sleepWindowInMilliseconds
断路器的快照时间窗,也叫做窗口期。可以理解为一个触发断路器的周期时间值,默认为10秒(10000)。
3、circuitBreaker.errorThresholdPercentage
断路器的窗口期内能够容忍的错误百分比阈值,默认为50(也就是说默认容忍50%的错误率)。打个比方,假如一个窗口期内,发生了100次服务请求,其中50次出现了错误。在这样的情况下,断路器将会被打开。在该窗口期结束之前,即使第51次请求没有发生异常,也将被执行fallback逻辑。
综上所述,在以上三个参数缺省的情况下,Hystrix断路器触发的默认策略为:
在10秒内,发生20次以上的请求时,假如错误率达到50%以上,则断路器将被打开。(当一个窗口期过去的时候,断路器将变成半开(HALF-OPEN)状态,如果这时候发生的请求正常,则关闭,否则又打开)
https://github.com/Netflix/Hystrix/wiki/How-it-Works
服务 consumer-hystrix-dashboard8020
org.springframework.cloud
spring-cloud-starter-netflix-hystrix-dashboard
com.ak.demo
api-commons
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
@EnableHystrixDashboard
@SpringBootApplication
public class HystrixDashboard8020 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboard8020.class, args);
}
}
被监控的服务provider-hystrix-payment8007 要包含:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
启动类:@EnableCircuitBreaker
application.yml 暴露 hystrix.stream
端点
management:
endpoints:
web:
exposure:
include: hystrix.stream
访问http://localhost:8007/actuator/ 确保含有:http://localhost:8007/actuator/hystrix.stream
访问地址:http://localhost:8020/hystrix
hystrix dashboard 一次只能监控一个服务实例,使用 turbine 可以汇集监控信息,将聚合后的信息提供给 hystrix dashboard 来集中展示和监控。
consumer-hystrix-turbine8021
org.springframework.cloud
spring-cloud-starter-netflix-turbine
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
com.ak.demo
api-commons
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
server:
port: 8021
spring:
application:
name: hystrix-turbine-service
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
turbine:
app-config: PAYMENT-SERVICE
cluster-name-expression: new String("default")
添加 @EnableTurbine
和 @EnableDiscoveryClient
注解
@EnableTurbine
@EnableDiscoveryClient
@SpringBootApplication
public class HystrixTurbine8021 {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbine8021.class,args);
}
}
turbine 监控路径:http://localhost:8021/turbine.stream
在 hystrix dashboard 中填入turbine 监控路径,开启监控:http://localhost:8020/hystrix
turbine聚合了 PAYMENT-SERVICE 两台服务器的hystrix监控信息