在元旦期间公司搞了一次比较大型的跨年促销活动,这次活动比较给力,请求量大概比平时翻了有20倍,下午4点左右接到反馈会员系统出现问题,C端的用户无法进行微信登录,由于用户基本都是在门店,小程序无法登录导致用户无法打开小程序使用之前已经领好的优惠券,门店收银台排队比较长,用户体验比较差,开始陆续有用户投诉。
一线人员将此情况反馈给研发,研发立刻进行定位,通过监控初步判定为是会员接口出现了雪崩,耗时变的非常慢,前端调用这个接口的失败率非常高,导致用户端无法顺利登陆小程序。
研发人员发现会员接口耗时确实比较高,首先看了下机器的CPU,发现机器的负载还好,CPU不是很高,数据库也没什么压力,说明接口耗时高多半时间花费在了IO等待上,这个会员登录的服务流程里面有一次请求外部的调用,跟微信端的交互,怀疑是这个地方耗时比较高导致的整个服务耗时变高,但是这个地方没有加监控,所以也看不到具体耗时是在哪里。
在处理事故期间,第一优先级想的是如何快速恢复生产,至于具体的原因如果不能快速定位清晰,那么也不要花太多时间在这个上面,既然短时间无法确认耗时是外部接口的问题?还是网络的问题?那么先想办法解决眼前的问题。
采取的第一个方案是增加机器的进程数量,既然不是CPU是瓶颈,那么增加机器的进程数量在一定程度上可以缓解调用的压力,将进程数量从原来的N个调整到M个,CPU还是没有太大压力,但是增加完进程后并没有明显缓解当时的问题。
下一步想到的就是扩容,既然IO有瓶颈,那么就先简单粗暴的通过扩容来解决下,但是由于环境的问题,运维给的答复是扩容要20-40分钟,这个时间确实比较长,只能先让运维同步扩容着,然后再想其他方案。
第三步采取的措施是,调整框架的防雪崩的参数,给这个服务增加秒级的防雪崩策略,这个策略上了后,整个接口的成功率明显提高,C端也逐渐恢复了。这个时候距离一线反馈已经过去近1个小时了。
在这次事故处理过程中,最终起到关键作用的就是防雪崩的策略,但是这个策略在会员这个核心的模块里面并没有提前配置好,如果之前就配置了相应的策略,那么将会大大缩短这次事故的时间。这也体现了大家平时只关注做功能本身,对系统的健壮性考虑的不是很全面。或者根本就不了解什么是“雪崩”,为什么要加防雪崩的机制。
防雪崩机制是保障服务可用性以及微服务治理中的一个非常重要的机制。分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应。
服务雪崩效应是一种因服务提供者的不可用导致 服务调用者的不可用,并将不可用逐渐放大的过程.如果所示:
服务雪崩上图中A为服务提供者, B为A的服务调用者, C和D是B的服务调用者。 当A的不可用,引起B的不可用,并将不可用逐渐放大C和D时, 服务雪崩就形成了。
为什么会出现雪崩,主要有以下几种可能性?
1.请求量突然剧增,导致服务处理不过来,这是一个最常见的场景,这种一般通过常规的压测就可以发现性能的瓶颈问题。
2.所依赖的下游服务出现故障响应变慢,导致自己也响应变慢,这种情况也会引发雪崩。
3.缓存击穿,缓存击穿一般发生在缓存应用重启,所有缓存被清空时,以及短时间内大量缓存失效时。 大量的缓存不命中,使请求直击后端,造成服务提供者超负荷运行,引起服务不可用。
那么出现雪崩,应该如何处理?
1.做好降级。区分好强弱依赖,如果是弱依赖出现了不可用,那么可以做降级,不要因为这个弱依赖导致整个流程不可用。对于弱依赖服务,如果出现了大量异常,可以通过一些技术手段提供有损服务,确保核心业务不受影响。
降级弱依赖2.流量控制,当服务出现雪崩后,C端用户会发现有些页面打不开或者打开比较慢,这个时候用户通常的做法是再重新刷新一遍,这样就导致本来正常请求已经处理不过来,再加上大量的用户重试更是雪上加霜,所以这里要进行流量的控制,将超出能力之外的请求快速报错,快速返回,从而使得在能力范围内的请求可以正常响应,至少保证一部分请求是可以正常响应的,而不至于整个服务都被打死完全无法提供响应。
限制流量分为单机限流以及集群限流。目前我们框架采用的是单机限流的策略,类似漏洞算法,实时监测当前机器的请求队列,当堆积的请求数量超过一定阈值,那么就直接将这个请求丢弃,这样尽管一部分请求会报错,但是保证大部分在服务处理能力范围内的请求可以得到正常响应。
单机限流3.服务扩容。出现雪崩后,多半是服务提供响应的能力变弱,扩容也是一种解决方案,但前提是扩容的速度要快,目前业界如果上了云,基本可以实现自动扩容,目前我们还不具备这个能力,只能人肉手工扩容,效率还是比较低。
总结回顾:
这个事故首先是准备不充分,会员这个地方没有做好事前的压测准备。直接导致线上流量翻了几十倍后达到了服务的性能瓶颈,导致后面问题的发生。
另外出现问题后,从接到反馈到最终解决问题,将近花了1个小时的时间,这个对用户伤害太大,定位以及解决的时间话的比较长。定位问题过程中发现监控点没有打全,对微信的外部调用没有加监控,导致接口响应变慢后,不能第一时间判断具体原因是在哪里,只能先简单粗暴的扩容,然后通过防雪崩的机制将多余处理不掉的请求进行丢弃,并没有从根本上找到问题进行解决。
最后框架里明明已经支持了防止雪崩的配置,但是开发人员不熟悉这个配置,在事前没有配置上,出了问题后对该配置也不熟悉导致整个处理过程耽误了不少时间。
相信经历过这次事故,相关研发同学一定能搞清楚什么是雪崩,为什么做防雪崩的策略,但是线上的事故比较是少数,每次通过线上的事故来让大家真正体会设计的意图代价还是比较大的,所以希望能够看到本篇文章的研发同学同样能够感同身受的体会下,这如果是你的负责的模块,会不会有类似问题,在处理这个事故的时候会不会有更好的解决方案。
网友评论