我使用This进行socketio设置。我有两个不同的socketio服务器(比如server1和server2)运行在集群中,使用的是RedissonStoreFactory
我的问题是,如果任何客户端连接到server1,那么server2没有连接客户端的信息。即。如果2个客户端使用server1连接,并且如果我在server2上执行server.getAllClients(),它将返回空列表,而不是具有2个计数的列表。
这是我在两台不同机器上运行的代码。
@SpringBootApplication
public class Application {
private static final Logger LOGGER = Logger.getLogger(Application.class);
@Value("${test.socketio.hostName}")
private String socketIOHostName;
@Value("${test.socketio.port}")
private Integer socketIOport;
@Value("${test.dedisson.redissonAddress}")
private String redissonAddress;
@Autowired
private RedissonClient redissonClient;
@Bean
public SocketIOServer socketIOServer() {
LOGGER.info("Socket server starting on host=" + socketIOHostName + ", port=" + socketIOport);
Configuration config = new Configuration();
config.setHostname(socketIOHostName);
config.setPort(socketIOport);
StoreFactory redissonStoreFactory = new RedissonStoreFactory(redissonClient);
config.setStoreFactory(redissonStoreFactory);
SocketIOServer server = new SocketIOServer(config);
server.start();
LOGGER.info( "Socket server started");
return server;
}
/**
*
* @return
*/
@Bean
public RedissonClient getRedissonClient(){
LOGGER.info("creatting redisson client on redissonAddress="+redissonAddress);
Config config = new Config();
config.useSingleServer().setAddress(redissonAddress);
RedissonClient redisson = Redisson.create(config);
LOGGER.info("redisson client connected");
return redisson;
}
public Application() {
//Nothing to be done here
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
@Bean
public SpringAnnotationScanner springAnnotationScanner(SocketIOServer ssrv) {
return new SpringAnnotationScanner(ssrv);
}
}我更希望故障切换的两个实例condition.If server1关闭,然后server2会将通知发送到连接的客户端,但在我的情况下,server2不知道连接的客户端与server1。
发布于 2019-12-13 12:57:31
发布于 2017-12-12 14:58:24
如果2个客户端使用server1连接,并且如果我在server2上执行server.getAllClients(),它将返回空列表,而不是具有2个计数的列表。
这是意料之中的。Server2可能有一些关于使用server1连接的客户端的信息(因为他们使用带有发布/订阅的redis ),如sessionId (查看类BaseStoreFactory)等,但是server2没有与这些客户端连接,在server2和通过server1连接的客户端之间没有通道。想一想,在底层,当没有tcp套接字连接时,为什么server2可以与客户端通信。
我更希望故障切换的两个实例condition.If server1关闭,然后server2会将通知发送到连接的客户端,但在我的情况下,server2不知道连接的客户端与server1。
使用Nginx (带iphash)或集群顶部的任何代理,一旦一台服务器宕机,客户端将尝试重新连接,nginx会将其重定向到另一台服务器。从clinet的角度来看,这不会有太多延迟。
发布于 2021-07-09 12:14:13
我也遇到过类似的问题,并用我的“自我协议”解决了这个问题。
服务器A与client X连接,服务器B与client Y连接。我需要将私有消息从服务器A发送到客户端Y。该解决方案是通过在每个服务器中映射所有服务器主机的列表,并为每个服务器主机创建一个“内部客户端”来实现的。
每个内部客户端负责通知其各自的服务器目标,然后服务器可以检查客户端目标是否存在于其自身的客户端列表中。
给定一个服务器A,如果您想列出一个集群的所有客户端,您可以要求每个内部客户端向其连接服务器发送一个数据包,例如"REQUEST“,然后为"RESPONSE”消息创建一个监听器,并将结果添加到全局列表中。
build.gradle
implementation group: 'io.socket', name: 'socket.io-client', version: '1.0.0'服务器
Configuration config = new Configuration();
config.setHostname(LOCALHOST);
config.setPort(PORT);
config.setTransports(Transport.WEBSOCKET); // DONT FORGET THIS LINE !!!
Config redissonConfig = new Config();
redissonConfig.useSingleServer().setAddress("redis://192.168.0.24:6379")
.setPassword("myPass");
Redisson redisson = (Redisson) Redisson.create(redissonConfig);
RedissonStoreFactory redisStoreFactory = new RedissonStoreFactory(redisson);
config.setStoreFactory(redisStoreFactory);
SocketIOServer server = new SocketIOServer(config);
server.addEventListener("REQUEST", Object.class, (client, data, ackSender) -> {
server.getBroadcastOperations().sendEvent("RESPONSE", server.getAllClients());
});内部客户端
List<SocketIOClient> allClients = new ArrayList<>();
List<Socket> internalClients = new ArrayList<>();
String[] hostnames = { "http://localhost:8081", "http://localhost:8082" };
for (String hostname : hostnames) {
IO.Options opts = new IO.Options();
opts.transports = new String[] { WebSocket.NAME }; // DONT FORGET THIS LINE !!!
Socket socket = IO.socket(hostname, opts);
socket.on("RESPONSE", args -> {
List<SocketIOClient> currentList = (List<SocketIOClient>) args[0];
allClients.addAll(currentList);
});
socket.connect();
internalClients.add(socket);
}
for (Socket socket : internalClients) {
socket.emit("REQUEST", "foo"); // THIS LINE WILL FILL CLIENTS LIST, VIA CALLBACK, FOR EACH SERVER
}https://stackoverflow.com/questions/46538493
复制相似问题