WhatAKitty Daily

A Programmer's Daily Record

记一次并发环境下程序阻塞解决思路

WhatAKitty   阅读次数loading...

背景

近期在做公司的一个项目重构,大致业务是将房源同步到闲鱼APP。
近几天在同步过程中,由于某个特殊原因,需要将日志记录由线程池异步记录更改为工作线程同步记录;而在这个更改后,发现程序在后期执行越来越慢。

分析

其他服务是否大量占用数据库资源

首先怀疑数据库那边是否出现了其他程序大量占有数据库资源的情况(当时凌晨运行程序,同时其他服务也会在这个点运行一些调度任务,所以才会有这个怀疑),查询了一下RDS的监控,发现在这段期间的确出现数据库服务CPU达到满值的情况。

基于这个考虑,笔者打算在白天重新运行这个情绪,看看是否仍旧会出现这个问题。

结果在运行一段时间后,仍旧出现了之前的问题,其他服务占用资源导致阻塞的推测直接被笔者排除。

程序数据库的最大连接数参数是否未设置

笔者在排除其他服务占用的推测之后,突然想到在初期开发的时候,为了方便并没有设置数据库连接池的最大连接数参数,会不会是这个原因?
趁着程序仍旧在运行并且被阻塞,在本地执行如下命令,查询程序的数据库连接占用情况:

1
ps -ef | grep 程序进程名称
1
lsof -p 程序进程PID -nP | grep TCP

通过如上两个命令可以查看这个进程连接了多少个数据库连接,而笔者查看到了该进程整整占用了16个连接(笔者的应用,有两个数据源,每个数据源按照druid连接池默认设置有8个最大连接数),很好,查到问题了;由于连接数被消耗完,导致程序无法再获取新的连接,即程序被阻塞。

但是这里有个问题,为啥日志记录非同步化的时候不会出现这个问题。略一想,之前日志记录都是异步进行,就算被阻塞,也不会阻塞程序的运行。而且相对来说,由于工作线程少了日志的记录任务(另一线程执行日志记录),占用数据库连接的时间也会相对较短,所以不会有那么明显的不正常阻塞现象发生。

解决方案

至于如何解决,既然找到了问题的原因,那么解决办法就很简单了:增加数据库连接池最大连接数的参数值,笔者这边直接增加到了100。