Tomcat生产环境WebSocket连接失败,返回Connection: Upgrade, close
问题分析与解决方案
从你提供的请求/响应信息来看,核心问题是响应头中的Connection: upgrade, close不符合WebSocket协议规范——根据RFC 6455,WebSocket握手响应的Connection头必须只能包含upgrade值。这个额外的close指令会让客户端认为服务器要关闭连接,导致握手后立即断开。
结合你的环境差异(开发Tomcat8 vs 生产Tomcat7+RHEL+防火墙),我整理了几个最可能的原因和对应的排查/解决步骤:
1. 中间代理/防火墙篡改了响应头
你提到服务器位于机构防火墙之后,这是最常见的触发原因。很多企业防火墙或反向代理(比如Apache、Nginx)在处理SSL加密流量时,可能会自动添加Connection: close头,尤其是当它们没有正确配置支持WebSocket升级逻辑的时候。
排查与解决:
- 本地直接测试生产服务器:在生产服务器上使用
wscat(WebSocket客户端工具)或者curl发起握手请求,查看响应头是否包含close:
如果本地测试的响应头只有# 用wscat测试WebSocket连接 wscat -c wss://localhost/WSServer # 或者用curl模拟握手请求 curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Key: test" -H "Sec-WebSocket-Version: 13" https://localhost/WSServerConnection: upgrade,说明问题出在前端的防火墙/代理层。 - 配置代理支持WebSocket:如果是反向代理(比如Nginx),需要添加以下配置确保正确转发WebSocket请求,不修改头信息:
location /WSServer { proxy_pass http://your-tomcat-instance:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } - 联系防火墙管理员:确认防火墙的SSL检查功能是否篡改了HTTP头,需要配置规则允许WebSocket的
Upgrade和Connection头保持原样传递。
2. Tomcat 7的版本或配置问题
Tomcat 7对WebSocket的支持虽然存在,但早期版本可能存在握手处理的bug,或者默认配置没有正确启用WebSocket支持。
排查与解决:
- 升级Tomcat 7到最新补丁版本:Tomcat 7的最新稳定版本(比如7.0.109)修复了多个WebSocket相关的bug,建议升级后再测试。
- 检查Server.xml中的Connector配置:确保SSL Connector使用支持WebSocket的NIO协议,而不是旧的BIO协议:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA"/> </SSLHostConfig> </Connector> - 检查自定义Filter/Valve:如果你的应用或Tomcat配置了自定义的Filter或Valve,确认它们没有在响应中添加
Connection: close头。比如某些安全Filter可能会强制添加这个头,需要修改配置放行WebSocket请求。
3. 依赖或类加载问题
虽然开发环境正常,但生产环境的Tomcat可能存在依赖冲突,导致WebSocket实现没有正确加载。
排查与解决:
- 确认生产环境的依赖:确保你的WAR包中没有包含与Tomcat 7冲突的WebSocket API或实现JAR(比如
javax.websocket-api的版本是否兼容Tomcat7)。Tomcat7自带了WebSocket的实现,WAR包中不需要重复引入。 - 检查Tomcat的lib目录:确认
tomcat-websocket.jar和tomcat-websocket-api.jar存在于Tomcat的lib目录中,且版本与Tomcat7匹配。
额外验证点
你提到ServerEndpointConfig.Configurator.modifyHandshake和@OnOpen方法都没有触发,这说明WebSocket握手请求根本没有到达你的应用处理层——要么是中间层拦截了请求,要么是Tomcat没有将请求转发给WebSocket处理器。建议先排除代理/防火墙的问题,再检查Tomcat的配置。
内容的提问来源于stack exchange,提问作者TFrazee
相关产品推荐
相关产品推荐

