Spring Websocket(Sockjs+STOMPjs)升级后10秒内会话异常关闭问题
排查Spring WebSocket + SockJS + STOMPJS会话10秒内自动关闭的问题
我来帮你分析下这个问题——既然已经拿到了HTTP 101的协议升级响应,说明基础的握手流程是通的,但10秒内会话就关闭,大概率和心跳配置、客户端连接逻辑、服务器超时设置或者网络层面的拦截有关,给你几个具体的排查方向:
1. 优先检查SockJS的心跳配置
这应该是最常见的原因,SockJS默认的心跳超时正好是10秒,和你遇到的时间窗口完全吻合:
- 服务器端:在你的WebSocket配置类里,调整SockJS的心跳和断开延迟参数,确保和客户端匹配:
@Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/websocket") .withSockJS() .setHeartbeatTime(30000) // 把心跳间隔改成30秒,避免频繁检测 .setDisconnectDelay(5000); // 断开前的延迟时间,给客户端缓冲 } - 客户端:STOMP.js必须显式配置心跳,不然服务器端收不到客户端的心跳信号,就会在10秒后主动关闭会话:
const socket = new SockJS('/websocket'); const stompClient = Stomp.over(socket); // 配置心跳,outgoing是客户端发心跳的间隔,incoming是服务器端的,和服务器保持一致 stompClient.heartbeat.outgoing = 30000; stompClient.heartbeat.incoming = 30000;
2. 确认客户端是否正确订阅了STOMP目的地
有时候服务器会因为会话"空闲"(没有订阅任何主题/队列)而主动关闭连接。一定要确保客户端在连接成功后立即执行订阅操作:
stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); // 必须订阅至少一个目的地,比如你的业务主题 stompClient.subscribe('/topic/your-topic', function(message){ console.log('Received message: ' + message.body); }); });
3. 检查服务器端的WebSocket消息代理配置
除了SockJS的配置,Spring的消息代理也有自己的心跳设置,你可以显式配置来覆盖默认值:
@Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic") .setHeartbeatValue(new long[]{30000, 30000}) // 代理的心跳间隔,和SockJS保持一致 .setTaskScheduler(taskScheduler()); // 自定义调度器,确保心跳任务正常执行 config.setApplicationDestinationPrefixes("/app"); } @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(1); scheduler.setThreadNamePrefix("websocket-heartbeat-"); scheduler.initialize(); return scheduler; }
4. 排查网络层面的超时拦截
如果你的应用前面有反向代理(比如Nginx)或者负载均衡,这些设备可能会主动断开空闲的WebSocket连接:
- Nginx配置示例:在对应的location块里添加WebSocket支持和超时设置:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; // 把超时时间调长,比如1小时 proxy_send_timeout 3600s; - 另外也要检查防火墙是否有针对WebSocket连接的短超时限制,这部分可能需要运维协助确认。
5. 查看完整的会话关闭日志
你提供的日志被截断了,完整的CloseStatus代码和描述能直接定位问题。可以把日志级别调到TRACE,获取更详细的信息:
logging.level.org.springframework.web.socket=TRACE logging.level.org.springframework.messaging=TRACE
常见的关闭原因比如HEARTBEAT_TIMEOUT(心跳超时)、GOING_AWAY(服务器主动断开),能帮你快速锁定问题。
先从心跳配置和客户端订阅这两个方向入手,这是最容易触发10秒会话关闭的点。
内容的提问来源于stack exchange,提问作者Black Glix
相关产品推荐
相关产品推荐

