正文
例如,假如一组服务下拥有服务机器四台(ABCD),假设A机器的服务因为某种未知原因,完全不可用了,这个时候L5服务会主动将A机器自动从服务组里剔除,只保留 BCD 三台机器对外提供服务。
而在后续,假如A机器从异常中恢复了,那么L5再主动将机器A加回来,最后,又变成 ABCD 四台机器对外提供服务。
在过去的3年里,我们逐步将 AMS 内的服务,渐渐从写死IP列表或者主备状态的服务,全部升级和优化为 L5 模式的服务,慢慢实现了 AMS 后端服务的自我容错能力。
至少,我们已经比较少遇到,再因为某一台机器的软件或者硬件故障,而不得不人工介入处理的情况。我们也慢慢地从疲于奔命地处理告警的苦难中,被解放出来。
四、超时时间
1. 为服务和存储设置合理的超时时间
调用任何一个服务或者存储,一个合理的超时时间(超时时间,就是我们请求一个服务时,等待的最长时间),是非常重要的,而这一点往往比较容易被忽视。通常Web系统和后端服务的通信方式,是同步等待的模式。这种模式,它会带来的问题比较多。
对于服务端,影响比较大的一个问题,就是它会严重影响系统吞吐率。假设,我们一个服务的机器上,启用了100个处理请求的 worker,worker 的超时时间设置为5秒,1个 worker 处理1个任务的平均处理耗时是100ms。
那么1个 work 在5秒钟的时间里,能够处理50个用户请求,然而,一旦网络或者服务偶尔异常,响应超时,那么在本次处理的后续整整5秒里,它仅仅处理了1个等待超时的失败任务。
一旦比较大概率出现这类型的超时异常,系统的吞吐率就会大面积下降,有可能耗尽所有的 worker(资源被占据,全部在等待状态,直到5s超时才释放),最终导致新的请求无 worker 可用,只能陷入异常状态。
算上网络通信和其他环节的耗时,用户就等待了超过5s时间,最后却获得一个异常的结果,用户的心情通常是崩溃的。
解决这个问题的方式,就是设置一个合理的超时时间。例如,回到上面的的例子,平均处理耗时是 100ms,那么我们不如将超时时间从 5s 下调到 500ms。从直观上看,它就解决了吞吐率下降和用户等待过长的问题。
然而,这样做本身又比较容易带来新的问题,就是会引起服务的成功率下降。因为平均耗时是 100ms,但是,部分业务请求本身耗时比较长,耗时超过 500ms 也比较多。
例如,某个请求服务端耗时600ms才处理完毕,然后这个时候,客户端认为等待超过500ms,已经断开了连接。处理耗时比较长的这类型业务请求会受到比较明显的影响。
2. 超时时间设置过短带来的成功率下降
超时时间设置过短,会将很多本来处理成功的请求,当做服务超时处理掉,进而引起服务成功率下降。将全部业务服务,以一刀切的方式设置一个超时时间,是比较不可取的。优化的方法,我们分为两个方向。
(1) 快慢分离
根据实际的业务维度,区分对待地给各个业务服务配置不同的超时时间,同时,最好也将它们的部署服务也分离出来。
例如,天天酷跑的查询服务耗时通常为 100ms,那么超时时间我们就设置为 1s,某新手游的查询服务通常耗时为 700ms,那么我们就设置为 5s。这样的话,整体系统的成功率,就不会受到比较大的影响。
(2) 解决同步阻塞等待
“快慢分离”可以改善系统的同步等待问题,但是,对于某些耗时本来就比较长的服务而言,系统的进程/线程资源仍然在同步等待过程中,无法响应其他新的请求,只能阻塞等待,它的资源仍然是被占据,系统的整体吞吐率仍然被大幅度拉低。
解决的思路,当然是利用I/O多路复用,通过异步回调的方式,解决同步等待过程中的资源浪费。AMS 的一些核心服务,采用的就是“协程”(又叫“微线程”,简单的说,常规异步程序代码里嵌套比较多层的函数回调,编写复杂。
而协程则提供了一种类似写同步代码的方式,来写异步回调程序),以解决同步等待的问题。异步处理的简单描述,就是当进程遇到 I/O 网络阻塞时,就保留现场,立刻切换去处理下一个业务请求,进程不会因为某个网络等待而停止处理业务,进而,系统吞吐率即使遇到网络等待时间过长的场景,通常都能保持在比较高的水平。
值得补充一点的是,异步处理只是解决系统的吞吐率问题,对于用户的体验问题,并不会有改善,用户需要等待的时间并不会减少。
3. 防重入,防止重复发货
前面我们提到,我们设置了一个比较“合理的超时时间”,简而言之,就是一个比较短的超时时间。而在数据写入的场景,会引起新的问题,就我们的AMS系统而言,就是发货场景。如果是发货请求超时,这个时候,我们需要思考的问题就比较多了。
(1) 发货等待超时,发货服务执行发货失败。这种场景,问题不大,后续用户重新点击领取按钮,就可以触发下一次重新发货。
(2) 发货等待超时,发货服务实际在更晚的时候执行发货成功,我们称之为“超时成功”。比较麻烦的场景,则是每次都是发货超时,而实际上都发货成功,如果系统设计不当,有可能导致用户可以无限领取礼包,最终造成活动运营事故。