Spring Boot Admin健康检查引起的Spring Boot服务假死

问题现象

最近在spring boot项目中引入了 spring-boot-starter-actuator 后,测试环境开始出现服务假死的现象,

且这个问题十分怪异,只在多个微服务中的简称A的这个服务中出现,其他服务都没有出现这个问题,

之所以说他是假死,是因为只是http请求无法访问进去了,但是该服务的定时任务却可以定时执行。

问题排查

通过查看jvm的线程信息发现,假死的A服务中,存在很多目前正在waiting状态的http nio线程,

进一步跟踪这些线程的堆栈信息,发现他们都在Alibaba Druid连接池的获取Connection方法中等待获取到最新的Connection,

第一反应是不是连接泄露了,存在慢sql、阻塞住的sql,或者手动获取connection但是没有归还的现象,

于是通过在定时任务代码中打印连接池的状态,发现也没有这种情况,而且连接池的最大连接数设置的也挺大的。

初步定位

通过观察该连接池的链接对象,发现是一个sql server数据库,但是我们的项目配置连接的其实是mysql,

在代码中搜索发现了有一个手动创建连接池的地方,而这里是为了与一个客户的sql server数据库做同步使用的,但是在给其他的客户部署时,并不需要这个操作,代码如下:

这里的操作有一个最大的问题,就是当不设置Druid连接池的等待连接时间时,该时间是-1,即默认永远等待,永不超时

最终定位

有了上面的代码,则需要确认为什么获取不到connection?造成永远等待?

这很正常,因为其他的客户环境并没有sql server,完全无法连接上啊,这时候Druid连接池中的可用connection压根没有,

然后spring boot admin,又不停的通过http轮询检查服务健康状态,最终它的每次http请求都会陷入阻塞等待connection,加之http又没有设置连接超时时间,

最终健康检查http连接占满了服务的http连接,导致其他的请求无法进入。

解决与避免

这里存在几个问题

  1. 该代码应当在指定客户环境运行,其余客户不应当创建该连接池
  2. 连接池配置应当通过yml文件配置,这样可以尽快的发现系统中存在的相关io组件,并发现其配置的不正确性,spring boot支持多数据源配置。
相关推荐
Rain的Java大神之路7 分钟前
LeetCode 21 合并两个有序链表:一道 Easy 题,凭什么刷掉一半候选人?
java·后端·算法
仙逆GPT9 分钟前
ChatGPT、Codex工程机制:Agent把@Transactional方法改成异步执行,为什么数据会出现部分提交?
spring boot·chatgpt·codex·chatgptplus·chatgptpro
小白的码BUG之路11 分钟前
K8S -- 集群搭建环境基础
java·服务器·kubernetes
w_t_y_y12 分钟前
JWT(5)JWT+spring security
java·后端·spring
wenyq722 分钟前
LeetCode 152. Maximum Product Subarray
java·算法·leetcode
余额瞒着我当琳23 分钟前
C++异常,异常的概念,异常抛出与捕获,RAII 和智能指针的设计思路,C++标准库一些指针的使用
java·开发语言·c++·算法
切糕师学AI38 分钟前
K8s 滚动更新与 Spring Boot 优雅停机实战:如何做到真正的平滑发布?
spring boot·云原生·容器·kubernetes·k8s
花间相见40 分钟前
【macOS开发环境:Java配置】—— Mac上的Java版本管理-SDKMAN安装、多版本切换与项目实战
java·架构·个人开发
骑着蜗牛撵大象3271 小时前
大模型 SDK 编译就崩?用 CMakeLists 把 httplib、JSON 与 OpenSSL 装配成可复用的 ChatServer
android·java·c++·http·json·cmake·大模型sdk