机器重启worker线程打满问题处理及sofa-rpc预热原理分析
1. 背景
降本增效后,服务A集群C1内的实例由6台4c8g容器降为4台2c4g,服务日常运行情况及资源利用率还算稳定。但发现的问题是:部署新版本重启应用时,偶发会收到大量的工作线程打满告警。
2. 问题分析
- 告警产生的原因:应用底层框架sofa-rpc的worker线程池配置为:corePoolSize=a、maxPoolSize=a * 10、queueSize=0。即:该应用最多可同时处理a * 10个rpc client请求(更严谨地:对sofa-rpc来说粒度是到端口的,应该为“该应用的某端口P1最多可同时处理a * 10个rpc client请求”,也就是说应用内的两个服务提供者ProviderA和ProviderB分别映射到了端口P1和端口P2并分别设置了最大a * 10个线程,那么同一时刻内该应用最多可处理2 * (a * 10)个客户端请求),多余的请求进来会直接打日志并抛服务拒绝处理异常。而当告警平台检测到某个时间段内有超过指定数量的异常时就会给开发发送告警。很明显,主要原因是应用处理请求的速度跟不上产生请求的速度,即CPU资源不足。
- 重启时间段CPU使用情况如何:监控平台查看CPU使用情况,发现应用重启期间,CPU使用率、CPU使用量、系统平均负载明显升高,达到容器可用资源的峰值,随后下降并维持稳定水平。且异常集中抛出的那几秒正好在峰值前后。所以,是哪些代码在重启期间大量抢占CPU时间?
- 哪些代码在重启期间大量抢占CPU时间:
- 最近上线的版本并未涉及到复杂逻辑的改动,所以可以排除业务代码的问题。
- 基础框架升级了版本,是否框架问题:咨询了负责基础框架的同事并查看了改动部分代码,并无发现有啥异常。
- 登录容器,重启应用并立即执行
top -Hp pid
,发现有一个叫“C2 CompilerThread”的线程使用率达到90%,并维持了3秒左右,而这几秒刚好是“1.”中大量告警产生的时间段。两个c被打满了一个,剩下一个来处理业务逻辑,所以,基本上能判定是因为“C2 CompilerThread”这个线程导致的了。
- “C2 CompilerThread”线程是干嘛的:JIT编译热点代码时用的参考链接
- 为什么降配之前没有这种问题:白天流量单实例300qps左右,2c的实例平均每个c扛150qps还处于稳定状态。因此4c的容器分配一个c去做热点代码编译还剩3个c来扛300个请求并不会有任何问题。而对于降配后的容器,原本单个核心3秒只需处理450个请求变成了要处理900个,自然会处理不过来而抛异常。
3. 怎么解决问题
- 升配:2c日常使用率才30%多,升到4c闲置率非常大,且由于这个原因才刚降下来,不合理。
- 动态CPU资源:需要切换部署方式,切换之后需要进行一系列测试,无资源跟进,不合理。
- 客户端服务器通信框架用的是sofarpc,是否有提供服务预热功能:有,地址, 修改代码、测试,上线后问题解决。
4. sofarpc预热功能实现原理
待看代码分析
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 杰布是谁!