一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
socket服务集群状态下广播消息的处理
前文
本文内容为在工作中遇到的socket服务集群时,需要广播时的处理方案。方案之中难免有不足之处,还请指教。
问题描述
由于项目采用分布式微服务集群方案,因此当前socket服务有若干个。当客户端进行socket连接时,会随机连接到服务中的某一个。假设有a,b,c三个服务,可能客户端此时连接到服务a。而当另一服务需要进行广播消息发送时,可能消息到达的位置为服务b,此时则无法进行对于服务a上的客户端进行消息广播。因此也就出现了本文采用的解决方案。
解决方案
理论上而言,我们的目的就是单纯的想要通过服务对于所有客户端连接进行消息发送。很容易想到的一个思路是通过redis进行客户端连接的存储,但是该方法似乎对于netty的适配有一些问题,该方案实际的应用还需要进行部分改进。而具体而言,本方案主要引入消息队列进行处理。通过消息发送端将服务消息提供到kafka中,而每一个socket服务都进行kafka消息的消费。当然此处的kafka只是抛砖引玉,其他的消息队列同样可以完成该需求。只需要确保消息能够被所有服务消费到即可。具体来看一下关键几处的代码: kafka消费代码:
MessageProcessor processor = KafkaMessageProcessor.getProcessor(record.topic());
Boolean processResult = processor.process((String) record.value());
if(processResult){
consumer.commitAsync();
}else {
logger.error("topic = {}, offset = {}, value = {} 处理错误", record.topic(), record.offset(), record.value());
}
消息广播代码:
socketIOServer.getNamespace("/online_debugging").
getRoomOperations(Constants.CONTEXT_TENANT_ID + "_" + tenantId + "_"+
Constants.CONTEXT_USER_ID + "_" + userId).
sendEvent("message", messageDTO.getMessage());
具体解释一下,也就是在客户端连接时会加入到对应的nameSpace,并加入相应的房间。当服务收到kafka消息时,会将消息发送到对应的nameSpace下的对应房间,以此方式实现对于消息的广播,避免集群状态下部分客户端连接无法接收消息的问题。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。