• 解决分布式下Websocket共享问题


    解决分布式下Websocket共享问题

    解决方案有2种,一个是redis,一个是mq。其中redis没仔细研究,就直接用了mq。项目中用F5代理了2台应用服务器,如果发生方和接受方不在同一个服务器,就会出现有问题。

    下面就直接上代码

    bo类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @ToString
    public class Message {
    
        private Integer id;
        private String msg;
        /**
         * 消息状态,1-未读,2-已读
         */
        private Integer status;
        private Date sendDate;
        private Date readDate;
        private String from;
        private String to;
    
    }
    

    配置类

    @Configuration
    public class WebSocketConfig implements WebSocketConfigurer {
    
        @Autowired
        private MyHandler myHandler;
    
        @Autowired
        private MessageHandshakeInterceptor myHandshakeInterceptor;
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(this.myHandler, "/ws/{uid}")
                    .setAllowedOrigins("*")
                    .addInterceptors(this.myHandshakeInterceptor);
        }
    }
    

    核心类

    /**
     * @author WGR
     * @create 2021/1/20 -- 21:55
     */
    @Component
    public class MessageHandshakeInterceptor implements HandshakeInterceptor {
        @Override
        public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
            String path = serverHttpRequest.getURI().getPath();
            String[] ss =  path.split("/");
            map.put("uid",ss[2]);
            return true;
        }
    
        @Override
        public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
    
        }
    }
    
    
    @Component
    public class MyHandler extends TextWebSocketHandler {
    
        private static final Map<Integer,WebSocketSession> SESSIONS = new ConcurrentHashMap<>();
    
        @Autowired
        private JmsMessagingTemplate jmsMessagingTemplate;
    
        /**
         * 用于接收消息的方法
         *  destination: 队列的名称或主题的名称
         */
        @JmsListener(destination  = "topic01")
        public void receiveMessage(javax.jms.Message message){
            if(message instanceof javax.jms.TextMessage){
                javax.jms.TextMessage textMessage = (javax.jms.TextMessage)message;
                try {
                    System.out.println("接收消息:"+textMessage.getText());
                    com.dalianpai.websocket.bo.Message msg = JSONObject.parseObject(textMessage.getText(), com.dalianpai.websocket.bo.Message.class);
                    WebSocketSession session = SESSIONS.get(Integer.valueOf(msg.getTo()));
                    if ((session != null && session.isOpen())) {
                        try {
                            session.sendMessage(new TextMessage(msg.getMsg()));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
    
                } catch (JMSException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
        @Override
        public void handleTextMessage(WebSocketSession session, TextMessage message)
                throws IOException {
            System.out.println("获取到消息 >> " + message.getPayload());
            Message msg = JSONObject.parseObject(message.getPayload(),Message.class);
            System.out.println(msg);
            Object uid = session.getAttributes().get("uid");
            System.out.println(uid);
            //说明在这台服务器上
                String toId = msg.getTo();
                WebSocketSession toSession = SESSIONS.get(Integer.valueOf(toId));
                if ((toSession != null && toSession.isOpen())) {
                    //TODO 具体格式需要和前端对接
                    toSession.sendMessage(new
                            TextMessage(message.getPayload()));
                }else{
                    jmsMessagingTemplate.convertAndSend("topic01",message.getPayload());
                }
    
    
    
        }
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws
                Exception {
                Integer uid =  Integer.valueOf((String)session.getAttributes().get("uid"));
                session.sendMessage(new TextMessage(uid+", 你好!欢迎连接到ws服务"));
                SESSIONS.put(uid, session);
        }
    
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status)
                throws Exception {
                Integer uid =  Integer.valueOf((String)session.getAttributes().get("uid"));
                SESSIONS.remove(uid);
                System.out.println("断开连接!");
    
        }
    }
    

    测试

    image-20210121105619342

    image-20210121105639145

  • 相关阅读:
    <转>iOS SDK中使用NSXMLParser解析XML
    [原创]闲来无事,写了个c#的数据库附加工具,现附上源代码
    [转载]php数组操作foreach、each、reset、list
    [原创]xml序列化
    [原创]一个简单的药店用的会员积分管理系统
    [原创]我的cms项目
    简洁、标准的对联广告代码
    C#混淆 xenocode使用说明
    .net 随机数
    [原创]c# as用法
  • 原文地址:https://www.cnblogs.com/dalianpai/p/14305886.html
Copyright © 2020-2023  润新知