You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Liferay+Tomcat(Atomikos)线程阻塞致应用卡顿问题排查求助

问题描述

环境配置

基于Liferay + Tomcat + PostgreSQL的应用,Tomcat配置Atomikos作为事务管理器,数据源配置如下:

<Resource 
    name="jdbc/liferay"
    auth="Container"
    type="com.atomikos.jdbc.AtomikosDataSourceBean"
    factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
    uniqueResourceName="jdbc/liferay"
    maxPoolSize="500"
    minPoolSize="10"
    borrowConnectionTimeout="30"
    maxIdleTime="60"
    reapTimeout="0"
    maintenanceInterval="60"
    testQuery="SELECT 1"
    xaDataSourceClassName="org.postgresql.xa.PGXADataSource"
    xaProperties.serverName="${host}"           
    xaProperties.portNumber="${port}"           
    xaProperties.user="${user}"           
    xaProperties.databaseName="${database}"
    xaProperties.password="${password}"  
    />
    
<Resource 
    name="jdbc/service"
    auth="Container"
    type="com.atomikos.jdbc.AtomikosDataSourceBean"
    factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
    uniqueResourceName="jdbc/service"
    maxPoolSize="100"
    minPoolSize="10"
    borrowConnectionTimeout="30"
    maxIdleTime="60"
    reapTimeout="0"
    maintenanceInterval="60"
    testQuery="SELECT 1"
    xaDataSourceClassName="org.postgresql.xa.PGXADataSource"
    xaProperties.serverName="${host}" 
    xaProperties.portNumber="${port}"           
    xaProperties.databaseName="service"
    xaProperties.user="${user}"           
    xaProperties.password="${password}" 
  />

故障现象

应用随机出现卡顿(每小时数次),卡顿期间无法处理任何请求,线程数激增。

线程Dump分析

大部分线程处于BLOCKED状态,等待获取Atomikos连接池的锁:

"http-apr-443-exec-163" - Thread t@17821
   java.lang.Thread.State: BLOCKED
    at com.atomikos.datasource.pool.ConnectionPool.borrowConnection(ConnectionPool.java:127)
    - waiting to lock <8e7fbf9> (a com.atomikos.datasource.pool.ConnectionPool) owned by "http-apr-443-exec-10" t@223

而持有锁的线程处于RUNNABLE状态,但卡在PostgreSQL的SSL连接建立阶段:

"http-apr-443-exec-10" - Thread t@223
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:161)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:128)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:113)
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)
    at org.postgresql.core.PGStream.receiveChar(PGStream.java:443)
    at org.postgresql.core.v3.ConnectionFactoryImpl.enableSSL(ConnectionFactoryImpl.java:505)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:149)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:223)
    at org.postgresql.Driver.makeConnection(Driver.java:465)
    at org.postgresql.Driver.connect(Driver.java:264)

疑问

这可能是什么原因?是死锁还是Atomikos配置错误?


问题分析与解决方案

这不是死锁,而是Atomikos连接池锁被长时间持有导致的全局阻塞,具体原因和解决思路如下:

核心原因

  1. Atomikos连接池锁的设计缺陷:旧版本Atomikos的ConnectionPool.borrowConnection()方法中,整个连接获取(包括新建连接)流程都持有全局锁。当某个线程需要新建PostgreSQL连接时,若遇到SSL握手超时、网络延迟等情况,会长时间占用锁,导致所有其他请求线程阻塞在锁等待步骤上。
  2. PostgreSQL SSL连接延迟:持有锁的线程卡在enableSSL阶段,说明SSL握手过程存在不可控延迟(如网络波动、PostgreSQL服务器SSL处理缓慢、证书验证耗时等),且该延迟发生在锁的持有周期内,直接引发全局阻塞。
  3. 连接池配置不合理:
    • reapTimeout=0:关闭了空闲连接回收机制,可能导致连接池无法及时清理闲置连接,增加新建连接的概率;
    • borrowConnectionTimeout=30:超时时间过长,线程会在锁上等待更久,加剧卡顿范围。

解决方案

  1. 升级Atomikos版本:较新版本已优化连接池锁的粒度,将新建连接的逻辑移出锁范围,避免在锁内执行耗时的网络操作。
  2. 解决PostgreSQL SSL连接问题:
    • 排查网络链路稳定性,确认是否存在丢包、延迟波动;
    • 调整PostgreSQL SSL配置,比如使用更高效的加密算法,测试环境可临时禁用SSL(添加xaProperties.ssl=false到数据源配置);
    • 检查证书有效性及验证流程,优化证书加载速度。
  3. 调整连接池参数:
    • 设置合理的reapTimeout(如60),让空闲连接被及时回收,减少新建连接频率;
    • 降低borrowConnectionTimeout(如10),避免线程长时间阻塞;
    • 确保minPoolSize足够覆盖日常请求量,减少高峰时段新建连接的需求;
    • 匹配Tomcat线程池配置,避免线程数过多导致系统资源耗尽。
  4. 监控连接池状态:添加Atomikos连接池监控,跟踪连接的获取、新建、回收情况,排查是否存在连接泄漏或新建连接过于频繁的问题。

内容的提问来源于stack exchange,提问作者Udepentctrsp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:27:06