@zero1036
2019-03-25T11:08:34.000000Z
字数 5721
阅读 1240
Java-其他库
架构
- 熔断
- 隔离
- 缓存
熔断器执行逻辑
熔断器配置项清单
//开启熔断器
.withCircuitBreakerEnabled(true)
//熔断器强制打开
.withCircuitBreakerForceOpen(true)
//熔断器强制关闭
.withCircuitBreakerForceClosed(false)
//默认值20.意思是至少有20个请求才进行errorThresholdPercentage错误百分比计算。
// 比如一段时间(10s)内有19个请求全部失败了。错误百分比是100%,但熔断器不会打开,因为requestVolumeThreshold的值是20.
// 这个参数非常重要,熔断器是否打开首先要满足这个条件。
// 参考图实例【1】
.withCircuitBreakerRequestVolumeThreshold(20)
//设定错误百分比,默认值50%,例如一段时间(10s)内有100个请求,其中有55个超时或者异常返回了,
// 那么这段时间内的错误百分比是55%,大于了默认值50%,这种情况下触发熔断器-打开。
// 参考图实例【2】
.withCircuitBreakerErrorThresholdPercentage(50)
//半开试探休眠时间,默认值5000ms。当熔断器开启一段时间之后比如5000ms,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复。
//如果试探请求成功,熔断器关闭;如果失败,熔断器再次打开,继续等待下一个休眠窗口过去后再重试
// 参考图实例【3】
.withCircuitBreakerSleepWindowInMilliseconds(5000)
参考博文:http://www.coolxuewang.com/view/4
命令commandKey:默认情况下,命令名称来源于类名。Hystrix默认以commandKey作为信号量隔离的依据
分组groupKey:Hystrix使用命令分组将一起的命令进行管理,比如报告、警报、仪表盘或组/库。默认情况下,Hystrix使用 HystrixCommandGroupKey
来定义命令线程池,除非单独定义线程池。
通过设置命令组, Hystrix会根据组来组织和统计命令的告警、仪表盘等信息。那么为什么一定要设置命令组呢?因为除了根据组能实现统计之外, Hystrix命令默认的线程划分也是根据命令分组来实现的。默认情况下, Hystrix会让相同组名的命令使用同一个线程池, 所以我们需要在创建 Hystrix命令时为其指定命令组名来实现默认的线程池划分。
如果 Hystrix的线程池分配仅仅依靠命令组来划分,那么它就显得不够灵活了,所以Hystrix还提供了 Hystrixthreadpoolkey来对线程池进行设置,通过它我们可以实现更细粒度的线程池划分。
线程池threadKey:线程池key,如果在没有特别指定Hystrixthreadpoo1Key
的情况下,依然会使用命令组的方式来划分线程池。通常情况下,尽量通过Hystrixthreadpoolkey
的方式来指定线程池的划分,而不是通过组名的默认方式实现划分,因为多个不同的命令可能从业务逻辑上来看属于同一个组,但是往往从实现本身上需要跟其他命令进行隔离
策略 | 有线程切换 | 支持异步 | 支持超时 | 支持熔断 | 开销大小 | 支持限流 |
---|---|---|---|---|---|---|
信号量 | 否 | 否 | 否 | 是 | 小 | 是 |
线程池 | 是 | 是 | 是 | 是 | 大 | 是 |
信号量:
线程池
重要:Hystrix缓存只能用于同一线程同一请求的上下,且不同线程间缓存不共享。so,其实比较鸡肋,有部分情况下可能有用。
官方建议:HystrixRequestContext.initializeContext()
初始化是在filter中进行,但是每一次初始化之前的缓存就失效了,所以要测缓存,就只能在controller中调用两次,才能看到缓存的结果是否相同,在同一用户请求的上下文中,相同依赖服务的返回数据始终保持一致。
@CacheResult
注解使用
@Service
public class CustomerService {
@Autowired
private RestTemplate restTemplate;
@CacheResult(cacheKeyMethod = "getKey")
@HystrixCommand(
fallbackMethod = "goFallback",
groupKey = "customerGroup",
commandKey = "getCustomer")
public String getCustomer(@CacheKey("id") String id) {
RibbonMessage msg = restTemplate.getForObject("http://TG-RIBBON-SERVICE/ribbonAccept?id=" + id, RibbonMessage.class);
System.out.println(msg);
return msg.toString();
}
/**
* 注意,@CacheRemove必须配合@HystrixCommand使用才有效果
* @param id
* @return
*/
@HystrixCommand
@CacheRemove(commandKey = "getCustomer", cacheKeyMethod = "getKey")
public String clearCache(@CacheKey("id") String id) {
return id;
}
public String getKey(String id) {
return id;
}
public String goFallback(String id) {
return "error:" + id;
}
}
@HystrixCommand(
fallbackMethod = "goFallback",
groupKey = "customerGroup",
commandKey = "getCustomer", commandProperties = {
//超时
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200"),
//开启请求缓存
@HystrixProperty(name = "requestCache.enabled", value = "true"),
//设置熔断
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
//断路器的最小请求数
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "1"),
//休眠时间
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "200"),
//断路频率
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
public String getCustomer(String id) {}
通过properties
配置
配置项 | 默认值 | 说明 |
---|---|---|
hystrix.threadpool.default.coreSize | 10 | 线程池启动时的固定大小值,还不是通常概念上的“最大值”,对于CPU密集型的任务,通常建议的线程池大小等于操作系统CPU核心数即可(一般是CPU数*2);针对IO密集型的任务,比如需要调用某个外部的http服务,并且每次调用时间比较长,可以适当调大该数值用更多的线程把这些等待时间利用起来。 |
hystrix.threadpool.default.maximumSize | 50 | 最大线程数,超过coresize部分的线程在空闲一段时间后回回收 |
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize | true | 是否让hystrix.threadpool.default.maximumsize配置生效 |
hystrix.threadpool.default.maxQueueSize | 2000 | 线程等待队列大小,当任务数量超过配置的maximumSize时,多余的任务会进行等待队列,等待有线程空闲时执行;当设定的值为-1时,线程数量超过maximumSize的任务将会抛出异常。 |
hystrix.threadpool.default.queueSizeRejectionThreshold | 1000 | 由于等待队列不能动态修改大小,所以引进了queueSizeRejectionThreshold配置来进行动态变更;queueSizeRejectionThreshold应当小于maxQueueSize,当需要等待的线程总数大于queueSizeRejectionThreshold时,即使没有达到maxQueueSize,依然会被拒绝进行等待队列,我们可以在运行时对该配置进行动态修改。 |
hystrix.threadpool.default.keepAliveTimeMinutes | 1 | 当超出coreSize大小的线程空闲时间达到设定值时,将会被,回收。 |
hystrix.command.default.execution.isolation.strategy | THREAD | hystrix的隔离策略,可以使用线程池或者信号量模式,因为信号量是阻塞式的,推荐使用线程池。 |
hystrix.command.default.execution.isolation .thread.timeoutInMilliseconds |
1000 | hystrix任务执行超时时间,应当大于ribbon设置的连接超时时间与读超时时间的和,但不应该太大。 |
hystrix.command.default.execution.timeout.enabled | true | 是否启用任务超时设置,推荐使用,防止任务一直等待,无法释放资源。 |
hystrix.command.default.execution.isolation .thread.interruptOnTimeout |
true | 当任务执行时间已经超过设定的超时事件时,是否中断执行请求的线程的工作,推荐使用。 |
hystrix.command.default.execution.isolation .thread.interruptOnCancel |
false | 当请求服务的主线程被中断或取消的时候,是否中断执行请求的线程的工作。 |
hystrix.command.default.fallback.enabled | true | 是否启用hystrix fallback功能。 |
hystrix.command.default.fallback.isolation .semaphore.maxConcurrentRequests |
10 | 当请求失败的数量达到设定的该数值时,将会直接拒绝接下来一段时间内的所有请求;可根据服务的承载量自行设定 |
hystrix.command.default.circuitBreaker.enabled | true | 是否启用hystrix断路器功能。 |
hystrix.command.default.circuitBreaker .requestVolumeThreshold |
20 | 进行hystrix离合器判定的最小请求数量,即只有当请求的数量达到设定的值时,才会进行判定是否开启断路器。 |
hystrix.command.default.circuitBreaker .sleepWindowInMilliseconds |
5000 | 当断路器开启以后时间达到设定的数值时,会尝试关闭断路器,重新请求服务,如果请求成功,断路器将会保持关闭状态;否则会重新开启断路器。 |
hystrix.command.default.circuitBreaker .errorThresholdPercentage |
50 | 当请求的失败比例达到设定值时,会开启断路器。 |
hystrix.command.default.circuitBreaker.forceOpen | false | 是否强制开启断路器,置为true时,断路器将一直保持开启状态,并拒绝所有服务。 |
hystrix.command.default.circuitBreaker.forceClosed | false | 是否强制关闭断路器,置为true时,断路器将一直保持关闭状态,不管请求的失败比例有多大。 |
hystrix.collapser.default.requestCache.enabled | true | 在批处理请求中是否启用缓存。 |
hystrix.collapser.default.maxRequestsInBatch | Integer.MAX_VALUE | 当批处理请求中的请求总数达到设置的值时会触发批处理请求,默认为无限大,通过下面的配置触发请求 |
hystrix.collapser.default.timerDelayInMilliseconds | 10 | 当批处理请求被创建该时间值以后,会触发执行。 |
监控
https://hot66hot.iteye.com/blog/2155036
隔离策略最好的解释
https://blog.csdn.net/heyutao007/article/details/51006694
spring @CacheResult缓存示例:
https://www.cnblogs.com/wanggangblog/p/8550218.html
有提及缓存的策略,但未确定正确性
http://www.cnblogs.com/hellxz/p/9056806.html