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

Apache-Tomcat 9+mod_jk负载均衡会话终止故障排查求助

Apache-Tomcat负载均衡会话丢失与worker错误状态修复方案

问题核心分析

从配置和日志来看,当前架构存在三个关键问题:

  1. worker错误状态无自动恢复机制:单个worker(如node2)出现请求失败后,直接被标记为错误状态,无重试或恢复逻辑,导致绑定到该worker的粘性会话全部失效。
  2. 会话无冗余备份:开启sticky_session=True但未配置会话同步,worker故障时会话无法迁移到其他节点,用户被迫重登。
  3. 错误处理策略过于严苛:请求中途失败后直接判定worker不可用,甚至出现误判所有worker失效的情况。

配置修正方案

1. 完善单个worker的容错配置

给每个Tomcat worker添加以下参数,增强错误恢复能力:

# 每个node通用配置,替换x为1/2/3
worker.nodex.retries=3                # 请求失败后重试次数
worker.nodex.connection_pool_timeout=60000  # 连接池超时时间(毫秒)
worker.nodex.socket_timeout=30000     # Socket读写超时时间(毫秒)
worker.nodex.socket_keepalive=True    # 保持长连接,减少连接建立错误

2. 调整负载均衡器的会话与错误处理策略

修改loadbalancer节点配置,允许会话迁移并优化错误判定:

worker.loadbalancer.sticky_session_force=False  # 绑定worker不可用时,允许转发到其他节点
worker.loadbalancer.max_reply_timeouts=5        # 累计5次回复超时才标记worker为错误
worker.loadbalancer.fail_on_status=500,502,503,504  # 指定触发错误标记的HTTP状态码

3. 配置Tomcat会话同步(关键)

因为系统是审批管理应用,会话连续性要求高,必须开启会话复制:

  • 基于Tomcat内置集群:在每个Tomcat的server.xml中添加Cluster节点(需确保所有节点在同一网络广播域):
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
         channelSendOptions="8">
  <Manager className="org.apache.catalina.ha.session.DeltaManager"
           expireSessionsOnShutdown="false"
           notifyListenersOnReplication="true"/>
  <Channel className="org.apache.catalina.tribes.group.GroupChannel">
    <Membership className="org.apache.catalina.tribes.membership.McastService"
                address="228.0.0.4"
                port="45564"
                frequency="500"
                dropTime="3000"/>
    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
              address="auto"
              port="4000"
              autoBind="100"
              selectorTimeout="5000"
              maxThreads="6"/>
    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
      <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
    </Sender>
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
  </Channel>
  <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
         filter=""/>
  <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
  <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
            tempDir="/tmp/war-temp/"
            deployDir="/tmp/war-deploy/"
            watchDir="/tmp/war-listen/"
            watchEnabled="false"/>
  <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
  • 基于Redis会话存储:如果跨网络部署,推荐使用Redis存储会话,需添加Tomcat Redis会话插件,配置context.xml:
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
  <Store className="com.orangefunction.tomcat.redissessions.RedisSessionStore"
         host="redis-host"
         port="6379"
         database="0"
         maxInactiveInterval="1800"/>
</Manager>

4. 修复AJP连接器配置(针对日志"Tomcat already send headers"错误)

该错误多因AJP连接异常或大文件传输问题,修改每个Tomcat的server.xml中AJP连接器:

<Connector port="8109" protocol="AJP/1.3"
           redirectPort="8443"
           maxThreads="200"
           connectionTimeout="60000"
           packetSize="65536"  <!-- 支持大文件上传(PDF/Excel等) -->
           secretRequired="false" />  <!-- 根据Tomcat版本调整,避免认证错误 -->

完整修正后的workers.properties

worker.list=loadbalancer,status

#setup node1
worker.node1.port=8109
worker.node1.host=<ip of worker1>
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.retries=3
worker.node1.connection_pool_timeout=60000
worker.node1.socket_timeout=30000
worker.node1.socket_keepalive=True

#setup node2
worker.node2.port=8209
worker.node2.host=<ip of worker2>
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.retries=3
worker.node2.connection_pool_timeout=60000
worker.node2.socket_timeout=30000
worker.node2.socket_keepalive=True

#setup node3
worker.node3.port=8309
worker.node3.host=<ip of worker3>
worker.node3.type=ajp13
worker.node3.lbfactor=1
worker.node3.retries=3
worker.node3.connection_pool_timeout=60000
worker.node3.socket_timeout=30000
worker.node3.socket_keepalive=True

#setup the load-balancer
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2,node3
worker.loadbalancer.sticky_session=True
worker.loadbalancer.sticky_session_force=False
worker.loadbalancer.max_reply_timeouts=5
worker.loadbalancer.fail_on_status=500,502,503,504

# Status worker for managing load balancer
worker.status.type=status

验证步骤

  1. 重启Apache和所有Tomcat节点
  2. 模拟单个worker故障(停止node2),检查用户请求是否自动转发到其他节点,会话是否保留
  3. 查看mod_jk日志,确认worker错误状态会自动恢复,无"All tomcat instances failed"误报
  4. 测试大文件上传下载,验证AJP连接稳定性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:07:01