小白也能看懂的基础概念
我们先来想一个场景。你是否还能记得每年的某宝双十一秒杀,几乎都会看到“网络繁忙,稍后再试”的提示不说,而且还有一些功能直接是关闭的。比如2018年的收货地址编辑功能就是关闭的,以至于小马下了好多单,有些单想把地址从公司改为家都只能干着急。有小伙伴幸灾乐祸吐槽:“哈哈,某宝的服务器崩了”。小马在这里很负责任地告诉大家这很可能不是人家服务器崩了而是人家把服务给关了,在码农的世界里这叫“服务降级”。
那么啥是佩奇,不,啥是服务降级?就是当系统出现短时间内的高并发大访问量的时候,有的时候为了保证主业务服务的稳定,把次要的业务功能服务先关闭,把资源留给主业务的动作。也就是上面的某宝例子中,为了保证秒杀浏览商品,购物下单流程的稳定,收货地址编辑功能暂时被降级了,典型的弃车保帅行为。
细心的小伙伴要问了,弃车真的就可以直接保帅了吗?弃车了如果流量还是很大,那怎么办呢?嗯,我们举个栗子。假设原本马路有三条车道,右侧车道是卡车车道,但是遇到节假日车流太大,于是关闭了卡车的通行,把卡车道也留给了小车来缓解压力,这是把卡车通行的服务降级了。但其实节假日的流量还是很大,那只能临时再扩建几条道了,在码农的世界里,这叫“水平扩容”。那就算是财大气粗也不能无限制地扩容吧?一直扩建马路?
答案自然是否定的,我们要做限流熔断。啥意思呢?想象一下我们的电路保险闸机制,一旦过载就熔断跳匝,道理是一样的。还是举刚才的栗子。我们刚刚扩建了好几条道,这个时候突然某军区接到运输命令要出任务,于是大量的运输车也进来了,大堵车让其寸步难行,大量车流导致整个交通系统基本瘫痪。交警拿着大喇叭来了,“左车道运输车行驶,中间几个车道小车行驶,右侧卡车行驶”。嗯,交通立马复苏了,为运输车顺利开出了一条通道来执行任务,码农把这种操作叫作“资源隔离”,就是各走各道,小车流量大堵车只能堵小车的通行不能影响我运输车车道行驶。这样就解决了因局部错误导致的资源消耗级联到整个系统,导致整个系统雪崩。
好了,中间车道的小车不乐意了,“小车从各个路口一直进来,我这都动不了了。”。没事,交警还有招。通过大数据探头分析,计算出该路段的30分钟内最大承载的通过量是300辆,好了,第301辆开始探头就亮红灯,请不要进入该路段了,原路返回吧,因为进来了也走不动。这叫“限流熔断”,这个探头分析就是断路计算器或者叫熔断器。当然除了车流大,交通事故往往也是引起大堵车的罪魁祸首。交警在出现了事故的车道入口早早亮红灯提示:前方事故请勿驶入直接返回吧。车遇到事故指示灯亮红就不进来了直接返回,也可以认为这条车道被降级了,这叫“快速失败回退(Fallback),优雅降级”。当然你也可以等,等绿灯亮起再进来(探头会计算车流情况,当事故车道通行恢复正常就尝试亮绿灯给予通行,这个检查的过程叫“健康检查”),否则就是添堵。
几杯茶的功夫,我们已经通俗地聊完了Hystrix中涉及到的一些基本概念,是不是如此简单。趁热打铁,接下来让我们来正式揭开她的面纱。
What Is Hystrix?
Hystrix本是豪猪的英文单词(有趣的是,很多IT的技术栈都有它自己的专属代言动物,如PHP的大象,GO的土拨鼠等等),豪猪的身体强壮,体长55-77厘米,尾长8-14厘米,体重10-14千克。在自然界中,只是偶尔才有经验十分丰富的豹或猎狗,伺机将它踢翻,使其柔软的腹部朝上,才能将其制服。一旦豪猪的刺刺进了脸或皮肤里,就很难拔掉了,豪猪的刺会深深扎进肉里,引起伤口感染,给伤者带来巨大的痛苦,甚至导致死亡。可见其自我保护能力的强大。而把它用于限流熔断库的命名自然再贴切不过了。小马觉得其实Hystrix也有点像交警的职能,维护整个交通系统顺畅。
在分布式系统中,服务与服务之间依赖错综复杂,一种不可避免的情况就是某些服务将会出现失败。Hystrix是一个库,它提供了服务与服务之间的容错功能,“容错”主要体现在延迟和异常上,从而做到控制分布式系统中的联动故障。Hystrix通过隔离服务的访问点,阻止联动故障,并提供故障的解决方案,从而提高了这个分布式系统的弹性。
History of Hystrix
Hystrix 从一个弹性(resilience)工程项目中发展而来,这个工程项目是Netflix公司 API团队在2011年开始的一个项目。到2012,Hystrix持续发展、成熟,并且Netflix公司的多个团队使用Hystrix。今天,在Netflix内部,每天使用Hystrix隔离技术维护的隔离线程数量到达几百亿,几十亿 Semaphore隔离(默认的隔离策略是实现线程池隔离,另外一种隔离策略是信号量)。
目前在服务保障方面,除了Hystrix框架外,阿里巴巴公司开源的sentinel框架也是一个不错的可选方案。
Hystrix特性
1.依赖服务出现高延迟或者失败时,为系统提供保护和控制,提供容错;
2.在分布式系统中防止级联失败;
3.快速失败(Fail fast)同时能快速恢复;
4.提供失败回退(Fallback)和优雅的服务降级机制;
5.提供近实时的监控、报警和运维控制手段。
Hystrix是如何做到这么优秀的
首先,就是做资源隔离。如果不做资源隔离,且一切情况正常的话如下:
正常情况下相安无事
如果有一个服务异常,将耗尽所有资源,导致系统崩溃,从而其他请求正常服务的请求也得不到响应。如下:
出现服务异常,资源未及时释放
局部服务异常资源耗尽导致整个系统阻塞
于是,做完资源隔离后,各自服务异常互不影响,防止了级联错误导致的系统雪崩,如图。
资源隔离后的情况,局部不影响全局
那资源隔离后的限流熔断呢?Hystrix怎么实现的?别急,请往下滑。
Hystrix引入了熔断器,到达到一定流量或者一定的异常数量就触发熔断器的开关状态,以达到对后面的请求进行快速降级。如图。
Hystrix熔断器(脑补探头例子)
触发降级动作的4种情况如下:
1.run()方法抛出非HystrixBadRequestException异常;
2.run()方法调用超时;
3.熔断器开启拦截调用;
4.线程池/信号量是否跑满。
工作流程图如下:
Hystrix工作流程
Hystrix的健康检查:熔断开启后,隔段时间,默认5秒会尝试半开,放入一部分流量请求进来,相当于对依赖服务进行一次健康检查,如果恢复,则关闭熔断状态,恢复依赖服务。
Hystrix代码实例
光说不练咋行,作为一个码农该如何使用它呢?下面以HystrixCommand用继承的方式实现为例(JAVA)。当然首先应当载入对应依赖库。
继承类并重写业务方法和降级方法
调用实例
好了,就到这里吧。Hystrix在分布式微服务系统中对容错性、可靠性的贡献还是可圈可点的,入门和实战还是两码事,这里仅是做了一个抛砖引玉,详细的请参阅官方文档。
参考资料:
Hystrix wiki git官方文档