Netty-SocketIO 集群解决方案
Netty-SocketIO
作为一个Socket框架,使用非常方便,并且使用Netty开发
性能也有保证。但是,我在使用
Netty-SocketIO
框架时,却发现,国内的资料比较少,虽然有些Demo级别的技术分享,但是关于集群解决方案,并没有什么较好的解决方法。
所以,博主结合GitHub上的Issues
,实现了一种集群的解决方案。
一. 解决方案原理
使用Redis订阅\发布模式解决,实现多集群间通讯。
注:
1.官方好像推荐使用Redisson来解决集群问题,有兴趣的同学可以试试,我是没试出来。。
2.最新版Redis支持数据流存储,可通过缓存SocketIOClient
来实现,有兴趣的同学可以试试。
二.服务端
使用SpringBoot+Netty-SocketIO+Redis,可通过修改启动端口,模拟多服务端
1.版本
netty-socketio
: 1.7.11
spring-boot-
: 2.2.1.RELEASE
JDK
: 1.8
2.项目结构
3.架构\原理图
3.代码
com.lt.push.config
ClientCache
本地(数据中心)类
package com.lt.push.config;
import com.corundumstudio.socketio.SocketIOClient;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author litong
* @date 2019/11/6 16:01
*/
@Component
public class ClientCache {
/**
* 本地缓存
*/
private static Map<String, HashMap<UUID, SocketIOClient>> concurrentHashMap = new ConcurrentHashMap<>();
/**
* 存入本地缓存
*
* @param userId 用户ID
* @param sessionId 页面sessionID
* @param socketIOClient 页面对应的通道连接信息
*/
public void saveClient(String userId, UUID sessionId, SocketIOClient socketIOClient) {
HashMap<UUID, SocketIOClient> sessionIdClientCache = concurrentHashMap.get(userId);
if (sessionIdClientCache == null) {
sessionIdClientCache = new HashMap<>();
}
sessionIdClientCache.put(sessionId, socketIOClient);
concurrentHashMap.put(userId, sessionIdClientCache);
}
/**
* 根据用户ID获取所有通道信息
*
* @param userId
* @return
*/
public HashMap<UUID, SocketIOClient> getUserClient(String userId) {
return concurrentHashMap.get(userId);
}
/**
* 根据用户ID及页面sessionID删除页面链接信息
*
* @param userId
* @param sessionId
*/
public void deleteSessionClient(String userId, UUID sessionId) {
concurrentHashMap.get(userId).remove(sessionId);
}
}
EventListenner
事件监听/注册中心
package com.lt.push.config;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.UUID;
/**
* @author litong
* @date 2019/11/6 15:59
*/
@Component
public class EventListenner {
@Resource
private ClientCache clientCache;
/**
* 客户端连接
*
* @param client
*/
@OnConnect
public void onConnect(SocketIOClient client) {
String userId = client.getHandshakeData().getSingleUrlParam("userId");
UUID sessionId = client.getSessionId();
clientCache.saveClient(userId, sessionId, client);
System.out.println("建立连接");
}
/**
* 客户端断开
*
* @param client
*/
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
String userId = client.getHandshakeData(