RPC的超时设置,一不小心就是线上事故
上面这张监控图,对于服务端的研发同学来说再熟悉不过了。在日常的系统维护中,『服务超时』应该属于监控报警最多的一类问题。
尤其在微服务架构下,一次请求可能要经过一条很长的链路,跨多个服务调用后才能返回结果。当服务超时发生时,研发同学往往要抽丝剥茧般去分析自身系统的性能以及依赖服务的性能,这也是为什么服务超时相对于服务出错和服务调用量异常更难调查的原因。
这篇文章将通过一个真实的线上事故,系统性地介绍下:在微服务架构下,该如何正确理解并设置RPC接口的超时时间,让大家在开发服务端接口时有更全局的视野。内容将分成以下4个部分:
从一次RPC接口超时引发的线上事故说起
超时的实现原理是什么?
设置超时时间到底是为了解决什么问题?
应该如何合理的设置超时时间?
01 从一次线上事故说起
事故发生在电商APP的首页推荐模块,某天中午突然收到用户反馈:APP首页除了banner图和导航区域,下方的推荐模块变成空白页了(推荐模块占到首页2/3的空间,是根据用户兴趣由算法实时推荐的商品list)。
上面的业务场景可以借助下面的调用链来理解
RPC的超时设置,一不小心就是线上事故
APP端发起一个HTTP请求到业务网关
业务网关RPC调用推荐服务,获取推荐商品list
如果第2步调用失败,则服务降级,改成RPC调用商品排序服务,获取热销商品list进行托底
如果第3步调用失败,则再次降级,直接获取Redis缓存中的热销商品list
粗看起来,两个依赖服务的降级策略都考虑进去了,理论上就算推荐服务或者商品排序服务全部挂掉,服务端都应该可以返回数据给APP端。但是APP端的推荐模块确实出现空白了,降级策略可能并未生效,下面详细说下定位过程。
1、问题定位过程
第1步:APP端通过抓包发现:HTTP请求存在接口超时(超时时间设置的是5秒)。
第2步:业务网关通过日志发现:调用推荐服务的RPC接口出现了大面积超时(超时时间设置的是3秒),错误信息如下:
RPC的超时设置,一不小心就是线上事故
第3步:推荐服务通过日志发现:dubbo的线程池耗尽,错误信息如下:
RPC的超时设置,一不小心就是线上事故
通过以上3步,基本就定位到了问题出现在推荐服务,后来进一步调查得出:是因为推荐服务依赖的redis集群不可用导致了超时,进而导致线程池耗尽。详细原因这里不作展开,跟本文要讨论的主题相关性不大。
2、降级策略未生效的原因分析
下面再接着分析下:当推荐服务调用失败时,为什么业务网关的降级策略没有生效呢?理论上来说,不应该降级去调用商