一、前戏
Hystrix插件式对netflix.hystrix的一次封装,简单介绍下Hystrix
- 在2018年11月20日netflix已经停止了对其维护(soul内目前版本1.5.12)
- 目前市面大多数spring cloud项目,熔断与降级组件使用的依旧是Hystrix
- 主要包括命令执行(execution)配置、命令降级(fallback)配置、熔断器(circuit breaker)配置、度量统计(metrics)配置和请求上下文配置。
- 具有信号量模式与线程池模式
科普贴:https://www.jianshu.com/p/dc0410558fc9
https://cloud.tencent.com/developer/article/1650056
二、soul-admin配置
- 开启插件
运行Soul-admin,进入管理界面:系统管理 --> 插件管理 --> Hystrix ,点击编辑,把它开启
配置选择器选择器参照divide的匹配方式,让符合条件的http的请求,能被捕获到
- 配置规则
以下配置只是为了更容易出现测试效果,生产环境请勿模仿
失败降级URL在后面的测试中,测试失败,应该是根据请求格式有关。
个别配置项解释:
- 命令key:
HystrixCommandKey是Hystrix命令的唯一标识,准确来说是HystrixCommand实例或者HystrixObservableCommand实例的唯一标识。一般设置为具体的 路径接口
- 分组key:
HystrixCommandGroupKey是用于对Hystrix命令进行分组,分组之后便于统计展示于仪表盘、上传报告和预警等等,也就是说,HystrixCommandGroupKey是Hystrix内部进行度量统计时候的分组标识,数据上报和统计的最小维度就是分组的KEY。 一般设置为:contextPath
三、soul-Bootstrap
网关层需要引入依赖即可
org.dromara
soul-spring-boot-starter-plugin-hystrix
${last.version}
四、测试
- 测试用例来一发
触发降级的两个条件:满足最大/最小并发量,或者达到异常比例。
所以使用wrk压一下,让流量先上到阈值,便于触发
wrk -t4 -c32 -d10s http://localhost:9195/http/test/findByUserId?userId=2
启动测试一下::http://localhost:9195/http/test/findByUserId?userId=2
熔断的返回值如下,fallback依旧是没有成功,可能跟格式有关系
{
"code": 500,
"message": "Internal Server Error",
"data": "/http/test/findByUserId short-circuited and fallback failed."
}
五、源码分析
插件链的调用此处不再分析,请参考之前文章,直奔主题HystrixPlugin##doExecute
@Override
protected Mono doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
// some code .....
// 将admin配置的rule实例化,json反序列化创建HystrixHandle对象,用于初始化Command
final HystrixHandle hystrixHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), HystrixHandle.class);
// some code .....
// 创建HystrixCommand
Command command = fetchCommand(hystrixHandle, exchange, chain);
return Mono.create(s -> {
// 注册完整执行生命周期事件 :onCompleted、onError、onNext处理方式
Subscription sub = command.fetchObservable().subscribe(s::success,
s::error, s::success);
s.onCancel(sub::unsubscribe);
// 请求经过command洗礼后,判断是否当前已经进入熔断状态
if (command.isCircuitBreakerOpen()) {
log.error("hystrix execute have circuitBreaker is Open! groupKey:{},commandKey:{}", hystrixHandle.getGroupKey(), hystrixHandle.getCommandKey());
}
}).doOnError(throwable -> {
// 通过调试,doExecute执行异常,比如timeout才会执行此处
log.error("hystrix execute exception:", throwable);
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE, ResultEnum.ERROR.getName());
chain.execute(exchange);
}).then();
}
onCompleted:onNext/onError完成之后最后回调
onError:当产生异常时回调
onNext:获取结果后回调
在fetchCommand方法,用于生成是信号量模式还是线程池模式的Command
HystrixHandle中给了ExecutionIsolationStrategy默认信号量的默认值
六、小结
- 日拱一卒
- 疑问:Hystrix已经停止维护了,真实项目使用此插件是否存在安全隐患?