起因,因为获取数据的服务跟本服务无法在同一个注册中心下,于是没法走RPC只能http调用,这不可避免的会走到nginx上,于是引发了限流,导致503错误

第一次改进

设置随机缓存时间,从1800秒到3600秒,方法开始判断缓存是否存在,方法结束将最新值写入缓存中,如果http调用数据为空则直接返回默认值而不会走到方法最后设置缓存了。
原本运行良好,没有任何异常,结果http被调用接口改了一个需求挂了,导致每次http调用拿到的值都为空,导致每次都没有设置缓存,于是每次都会不停调用http方法,结果就是,Kibana上半个小时打印了将近一万六千次异常日志……

第二次改进

有了这个漏洞后只想弥补这个漏洞,于是加了一个状态,就是如果从http调用中返回空值,那么这个状态就开启,设置个过期时间,状态打开后请求就直接返回默认值,而不会走http了。但是忽略了一种情况,那就是同时很多请求过来,缓存此时已经过期,那么这些请求还是会跳过缓存而打到http请求上去。

第三次改进

缓存改为写更新,有一个定时器,每10分钟执行一次,调用http请求,将最新的数据更新到缓存中,这样写完以后发现时不时就是一个503,感觉又回到解放前了,查询日志发现是因为请求后面带的随机参数是System.currentTimeMillis(),最细粒度是毫秒,所以会有那么多重复请求,于是想着把System.currentTimeMillis()改成System.nanoTime(),纳秒总不会有重复值的情况了吧,改完了一部署,发现还是503,头疼……

第四次改进

灵机一动,想到服务器节点达到22个之多,每到时间定时任务就在22个节点上执行,其实只要一个节点运行就可以了嘛,于是果断找到问题,用redis的setIfAbsent控制每次只会在一个节点上执行定时任务即可,改完之后果然没再出现503

本文作者:oldmee
本文链接:https://oldmee.github.io/2021/01/17/multitenancy-503/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!