WebSocket常用于做后台消息推送,也可以做简易的IM聊天,由于WebSocket中的Session没有实现序列化接口的,我们无法将session序列化实现分布式部署,今天就来记录一种分布式的实现方案。

实现原理

首先我们讲的这种方式是利用redis订阅和发布模式来实现,大致过程:

  • 每个服务器记录连接,保存在内存当中
  • 当需要推送websocket消息的时候,同时在redis发布一个消息
  • 每个服务器订阅redis的消息,当监听到有消息时,每台服务器遍历自己内存当中的连接进行发送

这样我们就可以实现websocket的分布式部署,当然redis订阅和发布也可以用其他消息队列工具类实现。

实现过程

这里并不打算贴所有代码,只记录关键的一些代码,其余的可以网上查看相关资料,基于SpringBoot2.1.8实现。

pom文件引入redis和websocket

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--websocket-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

写一个redis发布器

@Component
public class PublishService {@AutowiredStringRedisTemplate redisTemplate;/*** 发布方法** @param channel 消息发布订阅 主题* @param message 消息信息*/public void publish(String channel, Object message) {redisTemplate.convertAndSend(channel, message);}
}

写一个redis监听器

public class SubscribeListener implements MessageListener {/*** 订阅接收发布者的消息*/@Overridepublic void onMessage(Message message, byte[] pattern) {String msg = new String(message.getBody());System.out.println(new String(pattern) + "接收消息:" + msg);//遍历本地内存当中的websocket连接...//拿到对应的websocket session就可以进行推送消息}}

配置下websocket

@Configuration
public class WebSocketConfig extends ServerEndpointConfig.Configurator{@Overridepublic void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request, HandshakeResponse response) {// 主要为了能在websocket打开连接时获取httpsession和当前登陆用户,此处跟本文内容没有关系HttpSession httpSession=(HttpSession) request.getHttpSession();//存入httpsessionsec.getUserProperties().put(HttpSession.class.getName(),httpSession);//存入当前用户sec.getUserProperties().put("user", ShiroUtils.getCurrentUser());super.modifyHandshake(sec, request, response);}/*** 自动注册使用了@ServerEndpoint注解声明的Websocket endpoint* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

配置redis消息发布订阅

/*** redis 消息监听 用于websocket 分布式处理* @param redisConnectionFactory* @return*/
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory){RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);//设置订阅topicredisMessageListenerContainer.addMessageListener(new SubscribeListener(), new ChannelTopic("socket_topic"));return redisMessageListenerContainer;
}

再写一个简易的存储工具类,这个就基于ConcurrentHashMap就能实现,不记录了。

最后来看websocket ServerEndpoint 方法

@OnOpen
public void onOpen(Session session, EndpointConfig config) {log.debug("websocket:打开连接");//将连接存入我们的缓存工具,这个工具就是简单的存储,代码自己写一个CacheSessionMap.put("可以是sessionId,也可以实当前用户ID",session);}@OnClose
public void onClose(Session session) {log.debug("websocket:关闭连接");//关闭的连接,我们将其移除CacheSessionMap.remove("可以是sessionId,也可以实当前用户ID");}@OnMessage
public void onMessage(Session session, String message) throws IOException {log.debug("websocket:消息来了");//用我们之前写的redis消息发布器,将这个消息发布到redispublishService.publish("socket_topic", message);
}

关于WebSocket分布式实现的一种方案相关推荐

  1. 搞懂分布式技术16:浅谈分布式锁的几种方案

    搞懂分布式技术16:浅谈分布式锁的几种方案 前言 随着互联网技术的不断发展,数据量的不断增加,业务逻辑日趋复杂,在这种背景下,传统的集中式系统已经无法满足我们的业务需求,分布式系统被应用在更多的场景, ...

  2. Redis实现分布式锁的7种方案

    https://www.cnblogs.com/wangyingshuo/p/14510524.html 七种方案前言 日常开发中,秒杀下单.抢红包等等业务场景,都需要用到分布式锁.而Redis非常适 ...

  3. 保证分布式数据一致性的6种方案

    问题的起源 在电商等业务中,系统一般由多个独立的服务组成,如何解决分布式调用时候数据的一致性? 具体业务场景如下,比如一个业务操作,如果同时调用服务 A.B.C,需要满足要么同时成功:要么同时失败.A ...

  4. java实现分布式事务的三种方案

    问题描述: 用户支付完成会将支付状态及订单状态保存在订单数据库中,由订单服务去维护订单数据库.由库存服务去维护库存数据库的信息.下图是系统结构图: 如何实现两个分布式服务(订单服务.库存服务)共同完成 ...

  5. 从一笔金币充值去思考分布式事务,五种方案详解!

    小Hub领读: 分布式事务,有很多种解决方案,你知道啥场景用哪种解决方案吗?有啥优势?瞧瞧这篇文章! 作者:郑郑好victorzheng 原文地址 https://juejin.im/post/5ba ...

  6. 分布式锁解决并发三种方案

    目录 为什么使用分布式锁? 分布式锁应具备的条件 三种实现方式 1.数据库锁 1.1 乐观锁 2.基于redis的分布式锁 3.基于Zookeeper实现分布式锁 4.三种方案的比较 分布式CAP理论 ...

  7. 分布式锁中的王者方案:Redisson

    我们先来看下 Redis 官网对分布式锁的说法: 而 Java 版的 分布式锁的框架就是 Redisson. 本篇实战内容将会基于我的开源项目 PassJava 来整合 Redisson. 我把后端. ...

  8. 面试官问:你讲讲分布式事务问题的几种方案?

    面试题 1.分布式事务了解吗? 2.你们是如何解决分布式事务问题的? 面试官心理分析 只要聊到你做了分布式系统,必问分布式事务,你对分布式事务一无所知的话,确实会很坑,你起码得知道有哪些方案,一般怎么 ...

  9. 集成 websocket 的四种方案

    集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency><groupId>org.springframework.boot</gro ...

最新文章

  1. 数据结构 - 有两个链表,第一个升序,第二个降序,合并为一个升序链表(C++)
  2. Windows Socket 最大连接数
  3. Bootstrap-CSS:表格
  4. 数据库高级知识——索引优化分析(一)
  5. java excel 多个sheet_Java Excel导出多个工作表(添加多个sheet)
  6. OFBiz + Opentaps 目录管理 六. 产品目录
  7. [绝对原创]从VS2003(.net1.1)升级到vs2005(.net2.0)全程跟踪记录
  8. 爬取微博的数据时别人用的是FM.view方法传递html标签那么jsoup怎么解析呢
  9. 关于Javascript, php的web公开课笔记
  10. 唯一分解定理 详解(C++)
  11. 2021年中国研究生数学建模竞赛D题——抗乳腺癌候选药物的优化建模
  12. 操盘手 李彪 照片[转]
  13. RK3399 M0 调试-启动
  14. 2020.07-Study_update.5
  15. epson连接计算机后无法打印,电脑连接爱普生打印机后无法打印如何解决
  16. Photoshop设计精讲精练(读书笔记)
  17. Win10专业版错误代码0xc0000225在吗修复?
  18. 乌卡时代下,企业供应链管理体系的应对策略
  19. Jenkins用户密码重置
  20. 华为云平台部署虚拟机-SinoDB

热门文章

  1. 【ASP.NET MVC】 路由机制:命名路由
  2. SPList和SPDocumentLibrary 通过代码更新审批状态
  3. Atitit 软件工程概览attilax总结
  4. 如何在Jsp上传图片
  5. DataSet DataTable操作
  6. 【大话数据结构算法】冒泡排序
  7. Python 前端框架【Bootstrap】
  8. [转:有种感觉叫佩服]一个程序员的奋斗历程
  9. 雷林鹏分享:PHP 字符串变量
  10. 基础运维:shell入门