你的位置:首页 > 软件开发 > 网页设计 > 亿级Web系统的高容错性实践

亿级Web系统的高容错性实践

发布时间:2016-05-10 14:00:18
亿级Web系统的高容错性实践 背景介绍大概三年前,我在腾讯负责的活动运营系统,因为业务流量规模的数倍增长,系统出现了各种各样的异常,当时,作为开发的我,7*24小时地没日没夜处理告警,周末和凌晨也经常上线,疲于奔命。后来,当时的老领导对我说:你不能总扮演一个“救火队长 ...

亿级Web系统的高容错性实践

亿级Web系统的高容错性实践

简单重试,要使用在恰当的场景。或者,主动计算服务成功率,成功率过低,就直接不做重试行为,避免带来过高的流量冲击。这种重试的机制,看似比较可用,而实际上也存在一些问题:例如,假如一组服务下拥有服务机器四台(ABCD),假设A机器的服务因为某种未知原因,完全不可用了,这个时候L5服务会主动将A机器自动从服务组里剔除,只保留BCD三台机器对外提供服务。而在后续,假如A机器从异常中恢复了,那么L5再主动将机器A加回来,最后,又变成ABCD四台机器对外提供服务。

在过去的3年里,我们逐步将AMS内的服务,渐渐从写死IP列表或者主备状态的服务,全部升级和优化为L5模式的服务,慢慢实现了AMS后端服务的自我容错能力。至少,我们已经比较少遇到,再因为某一台机器的软件或者硬件故障,而不得不人工介入处理的情况。我们也慢慢地从疲于奔命地处理告警的苦难中,被解放出来。

三、超时时间算上网络通信和其他环节的耗时,用户就等待了超过5s时间,最后却获得一个异常的结果,用户的心情通常是崩溃的。

解决这个问题的方式,就是设置一个合理的超时时间。例如,回到上面的的例子,平均处理耗时是100ms,那么我们不如将超时时间从5s下调到500ms。从直观上看,它就解决了吞吐率下降和用户等待过长的问题。然而,这样做本身又比较容易带来新的问题,就是会引起服务的成功率下降。因为平均耗时是100ms,但是,部分业务请求本身耗时比较长,耗时超过500ms也比较多。例如,某个请求服务端耗时600ms才处理完毕,然后这个时候,客户端认为等待超过500ms,已经断开了连接。处理耗时比较长的这类型业务请求会受到比较明显的影响。(2)解决同步阻塞等待(1)发货等待超时,发货服务执行发货失败。这种场景,问题不大,后续用户重新点击领取按钮,就可以触发下一次重新发货。

(2)发货等待超时,发货服务实际在更晚的时候执行发货成功,我们称之为“超时成功”。比较麻烦的场景,则是每次都是发货超时,而实际上都发货成功,如果系统设计不当,有可能导致用户可以无限领取礼包,最终造成活动运营事故。

第二种场景,给我们带来了比较麻烦的问题,如果处理不当,用户再次点击,就触发第多次“额外”发货。

例如,我们假设某个发货服务超时时间设置为6s,用户点击按钮,我们的AMS收到请求后,请求发货服务发货,等待6s后,无响应,我们给用户提示“领取失败”,而实际上发货服务却在第8秒执行发货成功,礼包到了用户的账户上。而用户看见“领取失败”,则又再次点击按钮,最终导致“额外”多发一个礼包给到这个用户。

例子的时序和流程图大致如下:这里就提到了防重入,简单的说,就是如何确认不管用户点击多少次这个领取按钮,我们都确保结果只有一种预期结果,就是只会给用户发一次礼包,而不引起重复发货。我们的AMS活动运营平台一年上线的活动超过4000个,涉及数以万计的各种类型、不同业务系统的礼包发货,业务通信场景比较复杂。针对不同的业务场景,我们做了不同的解决方案:

(1)业务层面限制,设置礼包单用户限量。在发货服务器的源头,设置好一个用户仅能最多获得1个礼包,直接避免重复发放。但是,这种业务限制,并非每个业务场景都通用的,只限于内部具备该限制能力的业务发货系统,并且,有一些礼包本身就可以多次领取的,就不适用了。

(2)订单号机制。用户的每一次符合资格的发货请求,都生成一个订单号与之对应,通过它来确保1个订单号,只发货1次。这个方案虽然比较完善,但是,它是依赖于发货服务方配合做“订单号发货状态更新“的,而我们的发货业务方众多,并非每一个都能支持”订单号更新“的场景。(3)自动重试的异步发货模式。用户点击领取礼包按钮后,Web端直接返回成功,并且提示礼包在30分钟内到账。对于后台,则将该发货录入到发货队列或者存储中,等待发货服务异步发货。因为是异步处理,可以多次执行发货重试操作,直到发货成功为止。同时,异步发货是可以设置一个比较长的超时等待时间,通常不会出现“超时成功”的场景,并且对于前端响应来说,不需要等待后台发货状态的返回。但是,这种模式,会给用户带来比较不好的体验,就是没有实时反馈,无法立刻告诉用户,礼包是否到账。4.非订单号的特殊防刷机制通常一个发货服务如果出现异常,大多数情况,在connect步骤就是失败或者超时,而如果一个请求走到等待回包(read)时超时,那么发货服务另外一边就有可能发生了“超时但发货成功”的场景。这个时候,我们将read超时的发生次数记录起来,然后提供了一个配置限制次数的能力。假如设置为2次,那么当一个用户第一次领取礼包,遇到read超时,我们就允许它重试,当还遇到第二次read超时,就达到我们之前设置的阀值2,我们就认为它可能发货成功,拒绝用户的第三次领取请求。这种做法,假设发货服务真的出现很多超时成功,那么用户也最多只能刷到2次礼包(次数可配置),而避免发生礼包无限制被刷的场景。但是,这种方案并不完全可靠,谨慎使用。

在发货场景,还会涉及分布式场景下的CAP(一致性、可用性、分区容错性)问题,不过,我们的系统并非是一个电商服务,大部分的发货并没有强烈的一致性要求。因此,总体而言,我们是弱化了一致性问题(核心服务,通过异步重试的方式,达到最终一致性),以追求可用性和分区容错性的保证。

四、服务降级,自动屏蔽非核心分支异常1.服务分离,大服务变成多个小服务这样做带来了很多好处:

(1)原来主存储的压力被分流。

(2)稳定性更高,不再是其中一个出问题,影响整个大的模块。

(3)存储之间是彼此物理隔离的,即使服务器硬件故障,也不会相互影响。另外一方面,流程的执行不能通过“口头约定”,也应该固化为平台程序的一部分,例如,活动上线之前,我们要求负责活动的同事需要验证一下“礼包领取逻辑”,也就是真实的去领取一次礼包。然而,这只是一个“口头约定”,实际上并不具备强制执行力,如果这位同事因为活动的礼包过多,而漏过其中一个礼包的验证流程,这种事情也的确偶尔会发生,这个也算是“人的失误”的另外一种场景。为了解决问题,这个流程在我们AMS的内部管理端中,是通过程序去保证的,确保这位同事的QQ号码的确领取过全部的礼包。做法其实挺简单的,就是让负责活动的同事设置一个验证活动的QQ号码,然后,程序在发货活动时,程序会自动检查每一个子活动项目中,是否有这个QQ号码的活动参与记录。如果都有参与记录,则说明这位同事完整地领取了全部礼包。同时,其他模块的验证和测试,我们也都采用程序和平台来保证,而不是通过“口头约定”。通过程序和系统对业务逻辑和流程的保证,尽可能防止“人的失误”。

这种业务配置检查程序,除了可以减少问题的发生,实际上也减轻了测试和验证活动的工作,可以起到节省人力的效果。不过,业务配置检查规则的建设并不简单,逻辑往往比较复杂,因为要防止误杀。

七、小结

原标题:亿级Web系统的高容错性实践

关键词:web

web
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。