Reputation: 1540
I'm currently implementing a backend to frontend message mechanism using SockJS and Stomp on my Spring Boot 2 + Angular 14 app
I get a random behaviour, sometimes everythings works, but sometimes the websocket doesn't receive any messages.
When it doesn't work, WS messages looks like this
But when it works
The main difference is that when it workds, it receive a CONNECTED frame and fire the subscription. I don't get why sometimes it doesn't receive the CONNECTED frame.
My backend configuration
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/socket/no")
.setAllowedOriginPatterns("*").withSockJS();
}
}
The frontend client (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
},
I feel like it's more likely to work when i open the angular app on a small page. For example my homepage has a lot of component and take some time to load. But when i open the app with the url of a simple grid view it has more chance to work but not all times.
Due to this feeling, i think it's a frontend issue. Maybe a required angular component for websocket not loader or something like this.
On the backend side i see this log after the connect frame sent
ms.w.s.h.LoggingWebSocketHandlerDecorator New WebSocketServerSockJsSession[id=naeygmcp]
Upvotes: 1
Views: 2371
Reputation: 1540
Finally, migrating from Spring Boot 2.4 to 2.7 solved the issue. Now my app is migrated to Spring Boot 3.0 since some month and the issue didn't came back
Looks related to this https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22971
Upvotes: 0
Reputation: 1540
I moved the client initialization from ngOnInit to ngAfterViewInit and it seems to work now.
I will continue to test this solution some days before marking this answer as accepted
EDIT : It was not the root cause of the problem
Upvotes: 0
Reputation: 1884
Your WebSocket thread pool might be exhausted. By default, the thread pool is configured with:
core pool size = CORE * 2
max pool size = CORE * 2
queue capacity = Integer.MAX_VALUE
A successful connected STOMP client will go through the following stages:
CONNECT
CONNECTED
SUBSCRIBE
SEND
The 1st one is just an HTTP request, so it won't use that thread pool. On the contrary, the remaining stages under STOMP protocol will all use the pool. Maybe there are some long-running requests in your app occupying the pool, causing clients stuck at the second stage.
A possible solution is adjust that pool:
@Configuration
@EnableWebSocketMessageBroker
public class DefaultWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration
.taskExecutor()
.corePoolSize(8)
.maxPoolSize(512)
.queueCapacity(32)
.keepAliveSeconds(30);
}
}
Upvotes: 1