Tomcat Websockets Across Multiple Servers

439 views Asked by At

Current Solution

I have a Java server (Tomcat) setup issue that I'm hoping someone can provide some guidance on. Currently my web application is a single-server that has a Java backend running on Tomcat 8.5. To handle Websocket connections, I keep a Map of all the javax.websocket.Session passed in the onOpen() method.

@ServerEndpoint("/status")
public class StatusMessenger
{   
    private static ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap();

    @OnOpen
    public void onOpen(Session session) throws Exception
    {
        String sessionId = session.getRequestParameterMap().get("sessionId").get(0);
        sessions.put(session.getId(), session);
    }

My application only broadcasts messages to all users, so the broadcast() in my code simply loops through sessions.values() and sends the message through each javax.websocket.Session.

public static void broadcast(String event, String message)
{
    for (Session session: sessions.values())
    {
       // send the message
    }
}
  1. I'm not even sure that's the correct way to handle Websockets in Tomcat, but it's worked for me for years, so I assume it's acceptable.

The Problem

I want to now horizontally scale out my application on AWS to multiple servers. For the most part my application is stateless and I store the regular HTTP session information in the database. My problem is this static Map of javax.websocket.Session - it's not stateless, and there's a different Map on each server, each with their own list of javax.websocket.Sessions.

In my application, the server code in certain situations will need to broadcast out a message to all the users. These events may happen on any server in this multi-server setup. The event will trigger the broadcast() method which loops through the javax.websocket.Sessions. However, it will only loop through the sessions in it's own Map.

How do I get the multi-server application to broadcast this message to all websocket connections stored across all the servers in the setup? The application works fine on a single-server (obviously) because there's only 1 list of websocket sessions. In other words, how do I write a stateless application that needs to store the websocket connections so it can communicate with them later?

1

There are 1 answers

0
bluedevil2k On

I found 2 alternative solutions for this...

  1. In my load balancer I put a rule to route all paths with /{my websocket server path} to 1 server so that all the Sessions were on the same server.

  2. Use a 3rd party web push library like Pusher (http://pusher.com)