我目前正在我的 Spring Boot 2 + Angular 14 应用程序上使用 SockJS 和 Stomp 实现后端到前端消息机制
我得到一个随机行为,有时一切正常,但有时 websocket 没有收到任何消息。
当它不起作用时,WS消息看起来像这样
但是当它起作用时
主要区别在于,当它工作时,它会收到一个 CONNECTED 帧并触发订阅。我不明白为什么有时它没有收到 CONNECTED 帧。
我的后端配置
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/socket/no")
.setAllowedOriginPatterns("*").withSockJS();
}
}
前端客户端(app.component.ts > ngOnInit)
const socketUrl = `${window.origin}/socket/no`;
const stompClient = new Client({
brokerURL: socketUrl,
connectHeaders: {},
debug: function (str) {
console.debug(str);
},
reconnectDelay: 5000,
webSocketFactory: function () {
return new SockJS(socketUrl);
},
onConnect: function () {
stompClient.subscribe("/topic/no", function (msg) {
console.log("message received");
});
},
});
stompClient.activate();
proxy.conf.json
"/socket/**": {
"target": "http://localhost:8080",
"secure": false,
"ws": true
},
我觉得当我在小页面上打开角度应用程序时它更有可能工作。 例如,我的主页有很多组件,需要一些时间才能加载。但是,当我使用简单网格视图的 url 打开应用程序时,它有更多的机会工作,但并非总是如此。
基于这种感觉,我认为这是一个前端问题。也许是 websocket 所需的角度组件而不是加载器或类似的东西。
在后端,我在发送连接帧后看到此日志
ms.w.s.h.LoggingWebSocketHandlerDecorator New WebSocketServerSockJsSession[id=naeygmcp]
您的 WebSocket 线程池可能已耗尽。默认情况下,线程池配置为:
core pool size = CORE * 2
max pool size = CORE * 2
queue capacity = Integer.MAX_VALUE
成功连接的 STOMP 客户端会经历以下阶段:
CONNECT
CONNECTED
SUBSCRIBE
SEND
第一个只是一个 HTTP 请求,因此它不会使用该线程池。相反,STOMP 协议下的其余阶段都将使用该池。也许您的应用程序中有一些长时间运行的请求占用了池,导致客户端卡在第二阶段。
一个可能的解决方案是调整该池:
@Configuration
@EnableWebSocketMessageBroker
public class DefaultWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration
.taskExecutor()
.corePoolSize(8)
.maxPoolSize(512)
.queueCapacity(32)
.keepAliveSeconds(30);
}
}
最后,从 Spring Boot 2.4 迁移到 2.7 解决了这个问题。 现在我的应用程序已经迁移到 Spring Boot 3.0 一个月了,问题没有再出现
看起来与此相关https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22971