redis 的发布订阅解决分布式下的websocket session 共享问题

1.项目背景 :使用websocket 和前端通信但是后端是分布式部署,session 无法共享,并且websocketSession 无法序列化,所以无法把session存到redis 中。

2.基础代码:

java 复制代码
@Configuration
@Slf4j
public class RedisConfig {

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic(Constants.REDIS_CHANNEL));
        return container;
    }

    @Bean
    public MessageListenerAdapter listenerAdapter(RedisReceiver receiver) {
        return new MessageListenerAdapter(receiver, "onMessage");
    }


}
java 复制代码
@Slf4j
@Component
public class RedisReceiver implements MessageListener {

    @Autowired
    private TestHandler testHandler;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        try {
            log.info("RedisReceiver onMessage:{}",new String(message.getBody(), StandardCharsets.UTF_8));
            String channel = new String(message.getChannel());
            String content = new String(message.getBody(), StandardCharsets.UTF_8);
            if (Constants.REDIS_CHANNEL.endsWith(channel)) {
                testHandler.sendMessageToClient(content);
            }
        } catch (Exception e) {
            log.error("RedisReceiver 消息处理失败",e);
        }
    }

}
java 复制代码
@Slf4j
@Component
public class TestHandler extends TextWebSocketHandler {

    private static final ConcurrentHashMap<String, WebSocketSession> SESSION_DISPATCH_HOLDER = new ConcurrentHashMap<>();


    @Resource
    private StringRedisTemplate stringRedisTemplate;



    @Override
    public void afterConnectionEstablished(@NonNull WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SESSION_DISPATCH_HOLDER.put(session.getId(), session);
        log.info("webSocket already connected:{}",session.getId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        SESSION_DISPATCH_HOLDER.remove(session.getId());
        log.info("webSocket disConnect:{}",session.getId());
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
        log.info("handleMessage enter message:{}", JsonUtils.objToJsonStr(message.getPayload()));
        TextMessage textMessage = new TextMessage("");
        try {
            session.sendMessage(textMessage);
        } catch (IOException e) {
            log.error("发送消息失败", e);
        }
    }

 

  
    public void sendMessageToClient(String contentList) {
        log.info("sendMessageToClient:{}", contentList);
        if (CollectionUtils.isEmpty(SESSION_DISPATCH_HOLDER)) {
            log.info("没有连接中的客户端");
            return;
        }
        SESSION_DISPATCH_HOLDER.values().parallelStream().forEach(session -> {
            try {
                TextMessage textMessage = new TextMessage(contentList);
                session.sendMessage(textMessage);
                log.info("websocket 消息推送成功:{}", contentList);
            } catch (Exception e) {
                log.error("发送消息失败", e);
            }
        });
    }



}
相关推荐
摇滚侠10 小时前
Redis7 零基础到进阶 Linux 离线安装 Redis 09-10
数据库·redis·缓存
微三云 - 廖会灵 (私域系统开发)11 小时前
电商系统微服务拆分实战:从单体到Spring Cloud的分布式事务踩坑与补偿方案
分布式·spring cloud·微服务
techdashen12 小时前
Uber 的全局限流系统:从零散 Redis 限流到服务网格里的自动化流量保护
数据库·redis·自动化
ACP广源盛1392462567314 小时前
破局 PCIe 4.0 交换瓶颈@ACP#IX8024 / ASM58024参数及应用对比
大数据·人工智能·分布式·嵌入式硬件
宠友信息15 小时前
Redis 内容社区源码架构优化与即时通讯数据一致性处理
spring boot·后端·websocket·mysql·uni-app
淡然的煎蛋15 小时前
开始使用RabbitMQ
分布式·rabbitmq·ruby
这不小天嘛1 天前
JAVA八股——redis篇
java·开发语言·redis
烟漠河洛1 天前
线上事故复盘:Redis幂等性设计边界没覆盖跨状态请求,订单状态机直接崩了
数据库·redis·缓存
夜影风1 天前
Redis集群创建时出现“Node xxx.xxx is not empty”问题处理
数据库·redis·缓存