我们作为系统本身,既要关注上游系统的流量,也要关注下游系统或者中间件的响应。换而言之,就是注意自上而下一次请求的整体响应时间和请求量。作为中间系统,我们需要在上图中所有实线连接之处做防范。防止下游系统响应延迟或者是上游流量增加引起的导致的系统雪崩。
Hystrix简介
1:Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。
2:可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可.当调用超时时,直接返回或执行fallback逻辑。
3:为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。
4:依赖调用结果分:成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。
5:提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。
6:提供近实时依赖的统计和监控
调用链的使用
2.1.接口规划
2.1.1. 线程规划
原则上我们保证API所有请求最大线程并发数在10000 左右,根据接口相应的时间我们对长时间接口按照100个线程实现划分
这里补充下最大线程的概念:
在现有的框架里,我们使用的内嵌的tomcat容器,通过application.properties里的server.tomcat.max-threads来控制最大线程数。默认值为0;而如果要设置最大请求线程数,则需要获取tomcat的协议对象,对其对应属性来设置,默认是10000。我们为什么要控制在100呢?每个请求线程占用一定的JVM内存,为了保证JVM不会OOM。如果JVM堆栈较大或者每个请求较小,可以调高超时的线程数大小
一期
一期中,我们需要添加熔断的接口符合以下之一:
1)每次统计出的top10
2)普查接口调用在3S以上的所有API接口
2.2. 使用说明
2.2.1. API增加注解
/* groupKey :
* commandKey:
* threadPoolKey:三者值为一样,都为类名.方法名 如下:BizController.test
* execution.isolation.thread.timeoutInMilliseconds : 接口的最大超时时常(毫秒),此参数每个API不同,建议设置为TP99的时间,即100次调用,按照每次调用耗时正排序,第99个耗时
* 一般情况设置为此接口正常调用的最大超时时间
* circuitBreaker.requestVolumeThreshold:失败率达到多少个启动计算熔断 固定3;只有在一个统计窗口内处理的请求数量达到这个阈值,才会进行熔断与否的判断
* circuitBreaker.errorThresholdPercentage:失败率达到多少实现熔断,默认是成功率低于70开启熔断
* circuitBreaker.errorThresholdPercentage:失败率达到多少启动熔断 固定30
* coreSize:核心线程池大小,为此接口分配的线程,一般情况根据并发度来设置,QPS*TIMOUT*1.2
* maxQueueSize : 等待队列大小 ,固定长度 50 ,
* 异常封装即fallbackMethod将来做到eap-common里,返回特定result,
* fallbackMethod (非必须,建议):失败错误,降级错误方法名字
* fallbackMethod 定义方法签名必须和使用注解方法保持完全一致:即入参,出参 ;方法名建议:注解方法名+FallBack ,修饰权限:public
*
* 使用:1)需要设置groupKey、commandKey、threadPoolKey 为类名.方法名
* 2)execution.isolation.thread.timeoutInMilliseconds 根据接口设置为此接口正常调用的最大超时时间
* 3)coreSize 并发度来设置,QPS*TIMOUT*1.2
*/
@HystrixCommand(groupKey = "BizController.test", commandKey = "BizController.test",threadPoolKey = "BizController.test",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "50000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = Constants.HYSTRIX_CK_ERROR_NUMBER),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = Constants.HYSTRIX_CK_ERROR_TP)
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "12"),
@HystrixProperty(name = "maxQueueSize", value = Constants.HYSTRIX_MAX_QUEUE_SIZE)} ,fallbackMethod = "testFallBack")
@RequestMapping("/test")
public Result test(Integer a){
throw new IllegalStateException("ss");
}
/**
*定义方法签名必须和使用注解方法保持完全一致:即入参,出参 b奥驰完全一致;
* 方法名建议:注解方法名+FallBack ,修饰权限:public
*/
public Result testFallBack(Integer a){
Result result = new Result();
result.setCode(ErrorCode.STATUS_FAIL);
result.setMsg("接口调用异常,fallBack处理结果集");
return result;
}
网友评论