ThreadGroup引起守护线程中断的真实案例
场景描述:
MQ消费应用使用的druid连接池进行数据库操作,启动后一段时间(几小时到一天),出现获取不到数据库连接问题。druid连接池配置的是延迟加载,MQ消费客户端使用了线程组来进行线程管理,当线程组内的线程开始消费mq时,会触发druid连接池创建连接,并且初始化创建了两个守护线程:CreateConnectionThread、DestroyConnectionThread。也就意味着这两个线程隶属于MQ消费客户端内自定义的线程组,这两个守护线程的状态管理统一交给了MQ消费客户端的线程组进行了统一管理。所以当MQ在发生Failover时,收到REMOVE_BROKER事件,会关闭消费线程,并且会将自定义线程组的所有线程关闭(ThreadGroup.interrupt)。而druid连接池的两个守护线程也隶属于这个自定义线程组,所以也被中断了。这就导致了druid连接池中的连接处于了无人守护的地步,如果出现问题,也不再有线程进行检测和重连操作,从而导致druid连接池不可用。
所以针对以上场景的解决方案:
- 避免druid懒加载,在spring中配置init-method="init",应用启动时直接初始化连接池,这样也就确保守护线程隶属于main线程组。
网友评论