起因
在禅道上收到项目组提的一个故障:有一个业务接口,偶尔查不出数据,其它接口数据都正常,找不出原因,请求平台帮助排查。
项目架构介绍
springcloud微服务项目
注册中心:eureka
数据库:oracle
缓存:redis
orm:springJPA
反向代理:nginx
网关:zuul
容器化技术:docker
容器编排管理:k8s
CD/CI流水线:jenkins
排查过程
1.首先查看了服务器的日志信息,没有异常。
2.本地启了服务本地debug发现无法复现问题。(本地无法复现是很难受的,懂的都懂)
3.怀疑是注册中心注册了非法服务,导致请求轮询的时候轮询到非法服务查询到其他数据库,检查发现无其他非法服务被注册。
4.检查每个服务配置的数据库信息是否一致,检查结果数据库是一致的。(排查到这一步没发现异常,多少有点心灰意冷)
5.观察代码,无意中发现该业务接口使用了多线程,并且项目里有两个线程池,一个业务短信的线程池(标注了@Primary注解),一个专门给流程使用的线程池(没标注@Primary注解)。但是引入TaskExecutor的时候并没有指定name,导致系统内所有的业务都使用了同一个线程池,该线程池配置的最大线程数为16,最大队列数为64,线程池的拒绝策略为CallerRunsPolicy(由调用者处理,这也是日志没报错的原因)。
顺着思路,去服务器通过jps(ps -ef也行)命令查找到业务的进程pid,再通过top -Hp pid 查看到有大量的GC线程和短信线程一直执行,线程总数已超过了80个,导致后面发起的新线程不做任何处理。
6.要求项目组检查代码质量问题,然后检查短信发不出去的问题,最终问题得以解决。