spring boot websocket 集群环境处理

本文探讨了在后端系统中利用WebSocket替代轮询实现消息推送的实践,尤其是在集群环境下如何通过RabbitMQ解决WebSocket会话无法持久化的问题。文中详细介绍了使用RabbitMQ的FanoutExchange模式进行消息广播的方案,并通过动态创建队列来确保消息能够跨服务器传递。
摘要由CSDN通过智能技术生成

        开发中迎来一个功能重构,需要在后台系统给指定用户发送whatsApp消息。验证用户关系,用户回复后进行其他提问。原先开发这个功能负责人是基于轮询实现,看着频繁刷mongodb的日志心里不爽,决定尝试使用websocket 进行推送。

        通常实现websocket 方式有几种原生注解,spring 封装,及netty实现。 具体实现可以参考下此文https://www.cnblogs.com/kiwifly/p/11729304.html

       相信简单实现通信对工作1-2年之后的人并不是什么难事,哈哈 不就是使用api吗。具体通信代码就不贴了,没啥意思。主要是想记录一下,开发过程遇到的问题。了解websocket的相信都知道websocket中的session无法持久化,不像http中的session能持久化到redis之类。这对集群环境显然不是很美好,例如发送whatsApp消息后台操作人员连接到A服务器,给用户发送消息。A服务器收到发送消息请求,马上调用第三方消息接口发送。由于用户回复消息不是实时的,只能是提供一个回调地址给第三方。当今项目架构想必单机的情况基本不存在了吧,若是第三方回调A服务器上,则通过websocket正常推送。若回调到B服务,那么会话就不存在了。怎么解决呢?有人会说可以用nginx把用户请求都落到一个节点上,这样就使得程序失去负载均衡的意义了。反过来想想既然消息落到某台机器,是不是可以把消息分发到其他机器呢?广播一下消息即可。dubbo redis mq 都可以做相应的事。

     鉴于我们项目使用了RabbitMq,决定使用RabbitMq方式广播消息。用过RabbitMq肯定知道有种FanoutExchange模式的交换机,问题又来了FanoutExchange只会把消息广播到不同queue里。这时候心里又嘀咕了,同一套代码跟配置都是一样的。怎么搞呢?有没有法子呀,答案肯定是有的咯。可以声明queue的时候获取本机ip及进程id,这样就能产生不同的queue的名字了。动态创建queue及绑定交换机即可贴出部分代码

 

@Bean("webSocketFanoutExchange")
    FanoutExchange webSocketFanoutExchange() {
        return new FanoutExchange("webSocketFanoutExchange");
    }

    @Bean("webSocketQueue")
    public Queue webSocketQueue() {
        String name = "message.websocket.";
        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
            final String info = runtime.getName();
            final int index = info.indexOf("@");
            if (index != -1) {
                name = name + ip + "_" + info.substring(0, index);
            }
        } catch (UnknownHostException e) {
            log.warn("获取本地ip失败", e);
            name = name + UUID.randomUUID().toString().replace("-", "");
        }
        name = name + ".queue";
        return new Queue(name, false, false, true, null);
    }

    @Bean("bindingWebSocketExchange")
    Binding binding WebSocketExchange(@Qualifier("webSocketQueue") Queue  webSocketQueue,
                                             @Qualifier("webSocketFanoutExchange") FanoutExchange  webSocketFanoutExchange) {
        return BindingBuilder.bind(webSocketQueue).to(webSocketFanoutExchange);
    }

    @Bean(" WebSocketMessageContainer")
    public SimpleMessageListenerContainer  WebSocketMessageContainer(ConnectionFactory connectionFactory,
                                                                            @Qualifier("webSocketQueue") Queue  webSocketQueue,
                                                                            WebSocketMqListener webSocketMqListener) throws AmqpException {
		//WebSocketMqListener 你的消费处理
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.addQueues(webSocketQueue);
        container.setMessageListener(webSocketMqListener);//监听处理类
        return container;
    }
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值