订单服务用 HikariCP,maximumPoolSize 是五十,压测到一百五十并发时报 Connection is not available request timed out after 30000ms,数据库侧连接才用了三十个。

一开始怀疑是「连接池大小和线程池不匹配,线程全在排队」,查了一圈,方向不对。

排查方向其实有限,先把可能性排一排。连接被长时间占用,事务里夹了慢查询。还有一种是泄漏检测没开,没归还的连接一直挂在池里。

不容易想到的是,数据库侧有锁等待,把连接整体拖住。

动手时先看活跃连接数与等待数的实时值

curl -s http://10.0.0.11:8080/actuator/metrics/hikaricp.connections.active

再往下抓线程栈定位阻塞点

jstack $(pgrep -f order-service) | grep -A 12 'pool-' | head -60

随后查数据库侧有没有长事务

mysql -e "select trx_id,trx_started,trx_mysql_thread_id from information_schema.innodb_trx order by trx_started limit 10;"

缩短事务把远程调用移出边界

mysql -e "show variables like 'innodb_lock_wait_timeout';"

恢复的判定其实很直接。压测下活跃连接数稳定在四十以内,等待超时报错消失,接口 P99 从三十秒回落到两百毫秒。

连接池不是越大越好,连接数超过数据库核数太多反而增加切换开销;等超时先查是谁占着连接,别直接调大上限。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189