问题描述
当前解决方案
我遇到Java服务器(Tomcat)设置问题,希望有人可以提供一些指导。当前,我的Web应用程序是单服务器,具有在Tomcat 8.5上运行的Java后端。为了处理Websocket连接,我保留了Map
方法中传递的所有javax.websocket.Session
中的onopen()
。
@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);
}
我的应用程序仅向所有用户广播消息,因此代码中的broadcast()
只是循环访问sessions.values()
并通过每个javax.websocket.Session
发送消息。
public static void broadcast(String event,String message)
{
for (Session session: sessions.values())
{
// send the message
}
}
- 我什至不确定这是否是在Tomcat中处理Websockets的正确方法,但是它已经为我工作了很多年,所以我认为这是可以接受的。
问题
我现在想将AWS上的应用程序水平扩展到多个服务器。在大多数情况下,我的应用程序是无状态的,我将常规的HTTP会话信息存储在数据库中。我的问题是Map
的静态javax.websocket.Session
-不是无状态的,并且每个服务器上都有一个不同的Map
,每个服务器都有自己的javax.websocket.Session
s列表。
在我的应用程序中,某些情况下的服务器代码将需要向所有用户广播一条消息。这些事件可能会在此多服务器设置中的任何服务器上发生。该事件将触发broadcast()
方法,该方法遍历javax.websocket.Session
s。但是,它只会在自己的Map
中循环通过会话。
如何让多服务器应用程序将此消息广播到设置中所有服务器上存储的所有websocket连接?该应用程序在单服务器上运行正常(显然),因为只有1个Websocket会话列表。换句话说,我该如何编写一个无状态的应用程序,该应用程序需要存储websocket连接,以便以后可以与它们通信?
解决方法
我为此找到了2种替代解决方案...
-
在负载均衡器中,我制定了一条规则,将具有/ {my websocket服务器路径}的所有路径路由到1个服务器,以便所有会话都在同一服务器上。
-
使用第三方网络推送库,例如Pusher(http://pusher.com)