We have a design where the front end connects to backend nodes by Websockets. Consider an example where
Frontend node 1 (connects websocket) -----> server node1
Then server node1 cache the session id(session id 1) in the in memory of server node1 and goes off and does some activity.( sends some events to kafka etc)
Then downstream services do some action (consume events from kafka) and return a response to a redis stream
This time a new server node (server node2) can pick up the event from redis stream and has to send the response to that sessionid (session id 1) but since it does not have the webconnection details it ignores the event.
Only server node 1 is able to send response to that event because it has websocket connection details of session id 1
Is there a way for server node 1 to serialise the session id 1 and websocket connection details to a redis cache and when the server node 2 (as mentioned in step 4) picks up the redis stream even also reads the redis cache and desiarilise session 1 websocket connection and send the response to frontend node 1
IS THIS EVVEN possible
I have read many many articles and could not find any answer. All articles say that it is challenging but there is no place which says how to do it Please can i get some help in this issue
We are using spring-messaging package and hence i tried to serialise SimpMessagingTemplate object so that i can deserialise it back in the server node 2 for us to read the websocket connection
But it failed to serialise the object. May be i am missing something. SimpMessagingTemplate does not implement Serialisable interface
I need a solution to achieve the decoupling of websocket connection at the backend node (server node 1 to server node 2)
I’d be glad to assist you with designing a solution for decoupling Websocket connections between server nodes, ensuring that responses can be sent to the correct frontend node even when the initial connection is handled by a different server.
Here’s a proposed approach:
Session ID and Connection Details:
When a frontend node connects to a server node, store the session ID and relevant connection details (e.g., WebSocket endpoint, protocol) in a Redis cache using a key derived from the session ID.
Ensure that the cached data is serialized in a format that can be easily deserialized by other server nodes.
Event Processing and Response Generation:
Downstream services consume events from Kafka and generate responses.
When a response is ready, the service retrieves the session ID from the event and looks up the corresponding connection details in the Redis cache.
If the connection details are found, the service creates a new WebSocket session to the frontend node using the retrieved information.
The response is then sent through the newly created WebSocket session.
Code Example (using Spring Messaging and Redis):
Java
@Component
public class ResponseHandler {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private SimpMessagingTemplate messagingTemplate;
public void handleResponse(ResponseEvent event) {
String sessionId = event.getSessionId();
WebSocketConnectionDetails connectionDetails = (WebSocketConnectionDetails) redisTemplate.opsForValue().get(sessionId);
if (connectionDetails != null) {
// Create a new WebSocket session using the connection details
SimpleBrokerMessageHandler messageHandler = new SimpleBrokerMessageHandler();
messageHandler.setDestinationPrefixes("/topic"); // Adjust as needed
messageHandler.subscribe(connectionDetails.getEndpoint());
messagingTemplate.setMessageHandler(messageHandler);
messagingTemplate.convertAndSend(connectionDetails.getEndpoint(), event.getResponse());
// Remove the connection details from Redis after sending the response
redisTemplate.delete(sessionId);
} else {
// Handle the case where connection details are not found
log.warn("Connection details not found for session ID: {}", sessionId);
}
}
}
Key Points:
Redis Cache: Use Redis to store session ID and connection details for efficient retrieval and updates.
Serialization: Ensure that the connection details are serialized in a format compatible with both server nodes.
WebSocket Creation: Create a new WebSocket session using the retrieved connection details when needed.
Response Sending: Send the response through the newly created WebSocket session.
Cache Removal: Remove the connection details from Redis after sending the response to avoid unnecessary storage.
By following this approach, you can effectively decouple Websocket connections between server nodes and ensure that responses are delivered to the correct frontend node, even if the initial connection was handled by a different server.