Johan Frick opened SPR-12936 and commented

(This was posted on Stackoverflow as well, before we realized that you had a Jira. Let us know if you want us to remove it from Stackoverflow.)

We are trying to use spring-websocket with STOMP using SockJS as a fallback option. We have based our solution on this guide: https://spring.io/guides/gs/messaging-stomp-websocket/.

The environment is running multiple tomcats without sticky session.

The problem we have run into is that it is not possible to use the fallback from websocket due to the xhr requests ending up on separate tomcats where the original session does not exist, causing it to retry with a websocket connection and it will continue in this loop.

Is there a preferred way of solving this issue?

We were hoping that spring-session would be an answer but it does not seem to help in this case.


Affects: 4.1.5

Reference URL: http://stackoverflow.com/questions/29743065/spring-websocket-with-fallback-over-load-balancer

Issue Links: - #16243 Support user destinations with multiple WebSocket servers

0 votes, 8 watchers

Comment From: spring-projects-issues

Brian Clozel commented

Hi Johan Frick

Indeed, of your environment does not enforce sticky sessions, session replication is a good choice (and probably better anyway). spring-session should support this use case (see this dedicated guide); could you elaborate on how spring-session does not help with this?

Thanks!

Comment From: spring-projects-issues

Johan Frick commented

We've followed the guide that you linked, as well as the websocket guide for spring-session.

The problem seem to be that TransportHandlingSockJsService keeps it's own map of the sessions which is not shared between the tomcats.

Comment From: spring-projects-issues

Rossen Stoyanchev commented

The use of SockJS pretty much implies the use of sticky sessions. The protocol has a server id in the URL specifically for that (see here). In addition to TransportHandlingSockJsService there are other classes related to sub-protocol (STOMP) handling that also keep track of session specific information and they would also not work well with XHR and without server affinity. So this is not a bug but rather a design assumption.

Comment From: spring-projects-issues

Johan Frick commented

What is the reason for using Spring Session if the use of sticky sessions is required in the load balancer? In the Spring Session guide for websocket you are using SockJS: http://docs.spring.io/spring-session/docs/1.0.1.RELEASE/reference/html5/guides/websocket.html

Comment From: spring-projects-issues

Rossen Stoyanchev commented

Good point, about the use of SockJS in the example. I've created issue #196 to make a clarification on SockJS and server affinity.

To make sense of this, consider that SockJS is WebSocket emulation and WebSocket is a session on a single connection established once. To emulate this with HTTP fallback alternatives, many HTTP requests belonging to the same SockJS session are required, and those need to go to the same server where knowledge of the session is maintained. The alternative would be for every class involved in processing a session to use Spring Session and that's not the case. The core Spring Framework support is not even aware of Spring Session's existence, rather Spring Session builds on top.

That said there are other good reasons to use Spring Session with WebSocket and SockJS. I'll let Rob Winch comment.

Comment From: spring-projects-issues

Rob Winch commented

What is the reason for using Spring Session if the use of sticky sessions is required in the load balancer?

See if this helps explains why Spring Session and WebSocket makes sense: http://docs.spring.io/spring-session/docs/current/reference/html5/#websocket-why

Comment From: spring-projects-issues

Rossen Stoyanchev commented

I should also mention more explicitly that my main point is that the current behavior is by design. Spring Session does raise the possibility that we might be able to remove the need for server affinity when SockJS is used. It's just not the case now.

Comment From: spring-projects-issues

Johan Frick commented

Thanks for your detailed answers. I really wished that the outcome would be that we could avoid sticky sessions, but I guess that is not the case. We will do performance tests to see if we are satisfied with sticky sessions. Otherwise we would have to build our own solution outside of Spring. One day maybe Spring Session will have this support included, I hope.

Comment From: spring-projects-issues

Rossen Stoyanchev commented

Okay I'm turning this into an improvement request. It's certainly not something I can guarantee for 4.2 so it's in the 4.x backlog for now.

Comment From: spring-projects-issues

Johan Frick commented

Thanks for that, Rossen. We are happy to provide you with example code or help out with testing. Just let us know!

Comment From: spring-projects-issues

Petr Stuchlik commented

Rossen, could you please elaborate a bit, if/how this relates to #16243 ? Do we still need sticky session if MessageBrokerRegistry.userDestinationBroadcast is set? Thanks!