[TOC]
Objective
Recently, there was a problem in the company, and some websocket messages in the cluster were lost.
The problem is simple, and the service that sends the message is not the same service as the recipient's connected service.
Solution Solutions
Use Middleware (MQ, Redis etc) to communicate between services.
Instead of sending the WebSocket message directly, the message is placed in MQ or the Redis list.
and maintain the connection information in Redis, depending on the connection information, the service determines whether it needs to process the message or sends the message to the recipient's connected service.
code example
The spring WebSocket is used in our project, and the STOMP protocol is used to view the documents on the official website.
The code example only does the code example that maintains the connection information, and the rest of it is not put up.
code example for maintaining connection information
To maintain connection information for the STOMP protocol, you can view this part of the document listening to ApplicationContext Events and intercepting Messages
The connection information here is OK as long as it is able to identify different services.
This is part of the code that listens to the listener of the subscription event:
Package Cn.fjhdtp.websocket.interceptor;import Java.util.Map;import org.apache.commons.lang.StringUtils;import org.springframework.http.server.ServerHttpRequest;import Org.springframework.http.server.ServerHttpResponse;import Org.springframework.web.socket.WebSocketHandler;import Org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; Public classLogininfointerceptorextendsHttpsessionhandshakeinterceptor {@Override Public Boolean Beforehandshake(ServerHTTPRequest request, serverhttpresponse response, Websockethandler Wshandler, map<string, object> AttributesthrowsException {//Before shaking hands, add the required information to the attributesObject Loginbean = ...;//Get logged-in user information (or other information)Attributes.put(Websocketconstant.Websoket_loginbean, Loginbean);return Super.Beforehandshake(Request, response, Wshandler, attributes); }}
Package Cn.fjhdtp.listener;import org.springframework.beans.factory.annotation.Autowired;import Org.springframework.beans.factory.annotation.Qualifier;import Org.springframework.context.ApplicationListener;import Org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import org.springframework.stereotype.Component;import org.springframework.web.socket.messaging.SessionSubscribeEvent;import Java.util.Map;@Component Public classSessionsubscribeeventlistenerImplementsapplicationlistener<sessionsubscribeevent> {@Autowired @Qualifier("Serversidemessagetaskexecutor")PrivateThreadpooltaskexecutor Threadpooltaskexecutor;@Autowired PrivateImessagehandler MessageHandler;@Override Public void onapplicationevent(Sessionsubscribeevent event) {//Get subscription to DestinationString destination = (string) event.GetMessage().getheaders().Get("Simpdestination");//Get login informationObject Loginbean = ((Map) event.GetMessage().getheaders().Get("Simpsessionattributes")).Get(Websocketconstant.Websoket_loginbean);//todo Adding connection information to Redis}}
Package Cn.fjhdtp.message.listener;import Org.springframework.context.ApplicationListener;import org.springframework.stereotype.Component;import org.springframework.web.socket.messaging.SessionDisconnectEvent;import Java.util.Map;@Component Public classSessiondisconnecteventlistenerImplementsapplicationlistener<sessiondisconnectevent> {@Override Public void onapplicationevent(Sessiondisconnectevent event) {//Stomp connection disconnected, clear connection information //Get login information (or other information) from attributesObject Loginbean = ((Map) event.GetMessage().getheaders().Get("Simpsessionattributes")).Get(Websocketconstant.Websoket_loginbean);//Remove connection information from Redis}}
Of course, there may not be a normal trigger for disconnected events (there is no such event under was), so heartbeat is also required.
A simple record of spring websocket cluster problems