在AMS里,我们的后端涉及数以百计的各类服务,来支撑整个运营系统的正常运作。所有后端服务或者存储,首先是部署为无状态的方式提供服务(一个服务通常很多台机器),然后,通过公司内的一个公共的智能路由服务L5,纳入到AMS中。
(1) 所有服务与存储,无状态路由。这样做的目的,主要是为了避免单点风险,就是避免某个服务节点挂了,导致整个服务就瘫痪了。实际上,即使像一些具有主备性质(主机器挂了,支持切换到备份机器)的接入服务,也是不够可靠的,毕竟只有2台,它们都挂了的情况,还是可能发生的。我们后端的服务,通常都以一组机器的形式提供服务,彼此之间没有状态关系,支撑随机分配请求。
(2) 支持平行扩容。遇到大流量场景,支持加机器扩容。
(3) 自动剔除异常机器。在我们的路由服务,发现某个服务的机器异常的时候(成功率低于50%),就会自动剔除该机器,后续,会发出试探性的请求,确认等它恢复正常之后,再重新加回到服务机器组。
亿级Web系统的容错性建设实践 - 徐汉彬Hansion - 技术行者
例如,假如一组服务下拥有服务机器四台(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可用,只能陷入异常状态。
亿级Web系统的容错性建设实践 - 徐汉彬Hansion - 技术行者
算上网络通信和其他环节的耗时,用户就等待了超过5s时间,最后却获得一个异常的结果,用户的心情通常是崩溃的。
解决这个问题的方式,就是设置一个合理的超时时间。例如,回到上面的的例子,平均处理耗时是100ms,那么我们不如将超时时间从5s下调到500ms。从直观上看,它就解决了吞吐率下降和用户等待过长的问题。然而,这样做本身又比较容易带来新的问题,就是会引起服务的成功率下降。因为平均耗时是100ms,但是,部分业务请求本身耗时比较长,耗时超过500ms也比较多。例如,某个请求服务端耗时600ms才处理完毕,然后这个时候,客户端认为等待超过500ms,已经断开了连接。处理耗时比较长的这类型业务请求会受到比较明显的影响。
亿级Web系统的容错性建设实践 - 徐汉彬Hansion - 技术行者
2. 超时时间设置过短带来的成功率下降超时时间设置过短,会将很多本来处理成功的请求,当做服务超时处理掉,进而引起服务成功率下降。将全部业务服务,以一刀切的方式设置一个超时时间,是比较不可取的。优化的方法,我们分为两个方向。
(1) 快慢分离