Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring WebSocket Stomp tomcat cluster with user destinations sends message to wrong subscriber. [SPR-17228] #21761

Closed
spring-issuemaster opened this issue Aug 30, 2018 · 4 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Aug 30, 2018

Maksim Orlov opened SPR-17228 and commented

Tomcat uses AtomicLong for generating id for web socket sessions

private static AtomicLong ids = new AtomicLong(0);

at

org.apache.tomcat.websocket.WsSession;

then the id transferred to Spring WebSocket package

public void initializeNativeSession(Session session) {
		super.initializeNativeSession(session);

		this.id = session.getId();

at

org.springframework.web.socket.adapter.standard.StandardWebSocketSession;

In case of user destination subscriptions

stompClient.subscribe("/user/queue/events", callback, {  });

controller class

@MessageMapping("/thread")
@SendToUser(destinations = "/queue/events", broadcast = false)
public String handleThread(String rt) {
   return new Long(Thread.currentThread().getId()).toString();
}

will pass message to user queue on RabbitMQ with name "events-user0".

Sending message to "/app/thread"

stompClient.send("/app/thread", {priority: 9}, "Hello, STOMP");

will trigger controller with @MessageMapping. But in case when there is the second node and other client (different login) will also subscribe to "/user/queue/events" and its session id is the same as on the first node (because names just simple sequences ) The second user will receive the message instead of the first user, because first node created RibbitMQ queue with name "events-user0" and the second node subscribed to the +same+ queue.

The generated unique ids for the WebSocket session or different names for Broker queues can handle this issue.


Affects: 5.0.7

Reference URL: #17258

Attachments:

Issue Links:

  • #17258 Use UUID.randomUUID() for session id's in SockJsClient

Referenced from: commits b17e7c3, 3302798

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 4, 2018

Rossen Stoyanchev commented

Thanks for the report, indeed it looks like an issue.

Enabling SockJS, and using a SockJS client with the websocket transport listed as the only transport when connecting, is one potential workaround in the mean time. The SockJS sesssion id is generated by the client using a random seed supplied from the server on the initial "/info" URL. Subsequently when the WebSocket transport is used, the WebSocketServerSockJsSession wrapper uses the SockJS session id and ignores the one from the underlying WebSocket session.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 5, 2018

Maksim Orlov commented

As a fast workaround we changed +Tomcat+ to +Jetty+. Subsequently

StandardWebSocketSession 

has been substituted by

JettyWebSocketSession

that generate session id:

this.id = ObjectUtils.getIdentityHexString(getNativeSession());

It looks like little bit more reliable. But still

UUID.randomUUID()

can provide rely unique Ids for sessions.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 5, 2018

Rossen Stoyanchev commented

I've updated both the standard JSR-356 and the Jetty session to use a random id generated via AlternativeJdkIdGenerator

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 6, 2018

Maksim Orlov commented

Thanks a lot for the quick resolution of the issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.