一、技术分享
-
题引,用一个业务场景开启话题。
-
hystrix简单介绍
-
hystrix断路器的功能详细介绍
① 服务降级
② 依赖隔离
-
线程隔离
-
信号量隔离
③ *服务熔断
④ 服务监控
-
-
hystrix使用介绍
-
借助postman + hystrix dashboard 演示hystrix上述四大功能,jmeter对该接口进行压测观察吞吐量
-
总结
二、题引
三、hystrix功能简介
hystrix是Netflix开源的一款容错框架,防雪崩利器,是springcloud核心组件之一,是解决高并发问题三大利器之一。
hystrix针对一些正常执行的业务有限流的功能,针对突发的流量,它能够拒绝超出自身处理能力的请求,让这些请求直接走降级方法,快速响应给调用方;
针对一些异常和超时执行的业务有熔断和降级的功能,并且它还提供服务监控的功能来帮我们更好的了解接口的访问的成功、失败、超时、拒绝等请求数据,并且可以获取到该接口的线程池的使用情况,以便在测试时更好的控制线程池的参数;
针对一些核心的接口,hystrix还能将它和tomcat线程隔离,这些核心接口拥有自己的线程池,就算该接口阻塞线程过多线程池被打满,也不会影响其他接口的执行;
四、hystrix功能详解
1、服务降级
服务降级和openfeign的降级方法效果一样,方法体内抛出异常或者该方法执行超时之后会对当前方法进行降级执行。如果openfiegn和hystrix的超时时间都设置的话。分两种情况:
①openfeign的超时时间大于hystrix的超时时间,则走hystrix的降级方法。
②openfeign的超时时间小于hystrix的超时时间,openfeign会提前断开连接,走openfeign的降级方法;但是hystrix会继续执行业务代码直至完成或抛出异常。
一般我们会采用第一种方案,第二种方案有一个弊端就是,如果B服务涉及到事务,因为A服务提前执行降级方法,而B服务会继续执行完成;用户会认为我这次的操作没有成功(降级肯定意味着操作失败了),但实际B服务执行完成没有回滚。
2、依赖隔离
(1)线程隔离
线程隔离是将处理请求的tomcat线程池和执行调用方法的线程池做了一个隔离,请求线程并不执行具体的业务,而是由隔离的线程去执行,隔离线程执行完成之后交由请求线程响应给调用者,这就类似于一个线程将任务交给另一个线程去执行,用future来get执行结果,并发请求隔离受线程数量影响。
假设我们给B服务中的/provider/getUser路径的接口进行了线程隔离。
同样是A服务调用B服务,调用流程图:
(2)信号量隔离
信号量隔离有点类似于限流算法里面的计数限流,使用这种方式隔离,业务代码会由请求线程执行,但是执行前会判断信号量是否满。并发请求受信号量数量影响。
(3)两种隔离的区别
线程池隔离 | 信号量隔离 | |
---|---|---|
线程 | 请求线程和执行线程不是同一条线程 | 请求线程和执行线程是同一条线程 |
开销 | 排队、调度、上下文切换,开销较大 | 没有线程切换,开销低 |
异步 | 支持 | 不支持 |
传递http Header | 无法传递http Header | 可以传递http Header |
超时 | 支持 | 不支持 |
疑问:
什么时候用线程池,什么时候用信号量呢?
3、*服务熔断
hystrix的服务降级保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待。而服务熔断是hystrix监控我们调用的成功失败率之后,来决定后来的请求是否再去尝试执行业务代码。
注意熔断和降级的区别。
hystrix熔断器有三种状态:打开、半开、关闭
4、服务监控
hystrix自己提供了一个监控接口执行情况的面板,通过监控面板可以了解到使用hystrix接口的执行情况,下面是监控面板,里面包含了时间窗口内(默认10秒)该接口执行的成功数、降级数、超时数、拒绝数、失败数/总请求数以及熔断器状态等信息,方便我们更好的设置各项参数。
五、hystrix使用介绍
引入hystrix依赖:
<!--熔断器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--远程调用工具-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
首先在启动类上添加注解:
@SpringBootApplication
@EnableHystrix // hystrix启动类注解
@EnableHystrixDashboard // hystrix dashboard监控面板
public class HystrixProviderApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixProviderApplication.class, args);
}
/**
* 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
* ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
* 只要在自己的项目里配置上下面的servlet就可以了
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
application.yml文件添加配置参数:
# 暴露全部的监控信息
management:
endpoints:
web:
exposure:
include: "*"
# 允许本机查看监控信息
hystrix:
dashboard:
proxy-stream-allow-list: "localhost"
在需要熔断的接口上使用@HystrixCommand注解即可,核心是该注解的参数,该注解涉及到的参数很多。
@RequestMapping(value = "provider/{flag}", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
// 默认超时时间是1000ms,可通过以下进行设置 单位为ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000"),
// 打开熔断 默认开启
@HystrixProperty(name = "circuitBreaker.enabled", value = "false"),
// 当在配置时间窗口内达到此数量的失败后,进行短路。默认20个
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
// 短路多久以后开始尝试是否恢复,默认5s
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
// 出错百分比阈值,当达到此阈值后,开始短路。默认50%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),
// 设置为信号量隔离,Thread|Semaphore可选,默认Thread
// @HystrixProperty(name = "hystrix.command.default.execution.isolation.strategy", value = "Semaphore")
// 设置信号量数量,默认为10个
// @HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "30")
},
groupKey = "provider-group",
// 接口名称,默认为方法名
commandKey = "provider",
// 线程池名称,相同名称使用同一个线程池
threadPoolKey = "provider-threadPool",
threadPoolProperties = {
// 线程池大小,默认为10个线程
@HystrixProperty(name = "coreSize", value = "20"),
// 队列等待阀值(最大等待长度), 默认 -1
@HystrixProperty(name = "maxQueueSize", value = "100"),
// 线程存活时间,默认 1min
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
// 超出队列等待阀值执行拒绝策略
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")
}
)
public String provider(@PathVariable("flag") int flag) {
System.out.println(Thread.currentThread().getName() + "远程服务调用成功");
return "远程服务调用成功";
}
六、hystrix测试
postman + jmeter + hystrix dashboard演示hystrix功能
① 手动postman测试hystrix的降级、熔断机制(provider)
② jmeter演示hystrix线程隔离(provider)
③ jmeter演示熔断与不熔断该服务接口的吞吐量(consumer)
七、总结
集成hystrix的远程调用整个流程:
我们在做业务的时候不光要注重代码的健壮性,还要关注系统整体的一个稳定性和高可用。