Apache-Tomcat 9+mod_jk负载均衡会话终止故障排查求助
Apache-Tomcat负载均衡会话丢失与worker错误状态修复方案
问题核心分析
从配置和日志来看,当前架构存在三个关键问题:
- worker错误状态无自动恢复机制:单个worker(如node2)出现请求失败后,直接被标记为错误状态,无重试或恢复逻辑,导致绑定到该worker的粘性会话全部失效。
- 会话无冗余备份:开启
sticky_session=True但未配置会话同步,worker故障时会话无法迁移到其他节点,用户被迫重登。 - 错误处理策略过于严苛:请求中途失败后直接判定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
验证步骤
- 重启Apache和所有Tomcat节点
- 模拟单个worker故障(停止node2),检查用户请求是否自动转发到其他节点,会话是否保留
- 查看mod_jk日志,确认worker错误状态会自动恢复,无"All tomcat instances failed"误报
- 测试大文件上传下载,验证AJP连接稳定性
内容的提问来源于stack exchange,提问作者Shrijal Dave
相关产品推荐
相关产品推荐

