debug了很久,发现了Hystrix的两个bug

最近基于Hystrix源码添加一些花边功能,比如数据埋点、参数动态配置等,交付给业务之后,经过一系列的压测之后,发现了各种问题。

1、埋点数据有问题
2、熔断一直不恢复

先来看下埋点数据的问题,经过封装的Hystrix会把正常请求、试探请求、异常请求和熔断状态都记录下来,通过压测后发现发生熔断的时候,出现了好几个数据打点,正常情况下应该只有一个。通过debug,加日志之后,才发现这个隐秘的问题。

每次请求都会获取一个对应的熔断器,假设服务刚启动的时候,对应的熔断器还没有初始化,这时每个线程都会去尝试初始化一个,通过ConcurrentHashMapputIfAbsent方法保证最后拿到的是同一个熔断器,但是作者忽略了一个问题,在熔断器的初始化中,有这么一段逻辑:

上述逻辑中,熔断器在初始化时,会去注册Metrics的数据流的回调(本质是500ms执行一次,判断是不是达到熔断阈值了)。所以,如果有10个线程同时初始化熔断,虽然最终只会使用一个,但是其它9个熔断器也会注册回调。这就导致了当发生熔断时,熔断标识的埋点数据就有问题。

最好的办法就是初始化熔断器的时候,加个锁。

能避免的无效计算,都尽量的避免。

再来看看第二个问题,我觉得这算是一个大bug了,熔断一直不恢复,这意味着什么,意味着钱啊。

先看看什么情况下,熔断之后不会恢复吧。
熔断器内部有三个状态:CLOSEDHALF_OPENOPEN。默认情况下,都是处于CLOSED状态,当请求的失败率过高,达到阈值时,就自动从CLOSED切成OPEN,这是所有的请求会执行降级逻辑,这些都没问题。熔断开启之后,如果过了一个试探窗口(5000ms),其中一个请求线程会把熔断状态从OPEN切成HALF_OPEN,表明要开始试探下游服务是不是已经恢复了。如果下游已经恢复,那么这个请求正常返回之后,会执行markSuccess方法,该方法实现如下:

在这个方法中,会把熔断转态从HALF_OPEN切成CLOSED,熔断恢复,分析下来,好像这一切是那么的理所当然,顺理成章。

但是,但是!!!
在熔断开启期间,执行降级的请求最后会执行一个叫unsubscribeCommandCleanup的Action,代码如下:

在该Action中,执行circuitBreaker.markNonSuccess(),这个会导致什么问题?设想一下,如果试探请求刚把熔断从OPEN切成HALF_OPEN,正在等待下游返回时,这时一个降级请求,理所当然执行了markNonSuccess,顺带把熔断又从HALF_OPEN切成OPEN,一切都是默默的发生,不留下一丝痕迹,不加个日志,你都不知道发生了什么。

熔断状态被降级请求切回了OPEN,这时试探请求结果成功返回,执行markSuccess方法,准备把熔断从从HALF_OPEN切成CLOSED,殊不知已经被内部间谍提早偷偷换了转态,就导致了应该恢复的服务,继续降级着,只能祈祷下次没有降级请求提早偷换状态。

去github上翻了一下,在1.5.12版本中,Action unsubscribeCommandCleanup并不会执行 circuitBreaker.markNonSuccess(),而是在1.5.13中,为了修复一个bug而加入的。

加这段代码的本意是:Fixed bug where an unsubscription of a command in half-open state leaves circuit permanently open,就是下面这种写法。

Observable<Boolean> o = cmd5.observe();
Subscription s = o.subscribe();
s.unsubscribe();

结果,种下了另一个隐患,而这个问题17年7月就被种下了,迟迟未得到修复,Hystrix难道没人维护了?

如果想用原生的Hystrix,建议使用1.5.12版本;
如果想用最新的版本,建议对源码进行适当的修改,再进行使用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • (git上的源码:https://gitee.com/rain7564/spring_microservices_...
    sprainkle阅读 9,339评论 13 33
  • 微服务 微服务就是一个独立的可部署的占有自己进程的一个实体, 我们一般把这个实体称之为服务。 微服务的核心思维和S...
    勇敢的_心_阅读 1,249评论 1 7
  • 一、前言 在分布式系统架构中多个系统之间通常是通过远程RPC调用进行通信,也就是 A 系统调用 B 系统服务,B ...
    阿里加多阅读 22,626评论 0 11
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 开篇  对Hystrix耳闻已久,最近刚好想在项目中使用这个神器就顺带研究了一把,很多细节来不及深入研究只能把宏观...
    晴天哥_王志阅读 6,761评论 0 3