炫技亮点 Websocket集群解决方案汇总

文章目录

    • 问题
    • 方案
      • 方案一:~~Session共享~~(不可行)
      • 方案二:负载均衡器(状态路由)
      • 方案三:广播机制(异步方式 - 建议)
      • 方案四:路由转发(同步方式)
      • 方案五:高可用(多活冗余)

问题

假设我们有一个聊天应用程序,其中客户端通过WebSocket与服务器进行实时通信。在单机环境下,所有的WebSocket连接都由单个服务器处理。

单机场景

用户A、用户B和web服务器建立连接之后,用户A发送一条消息到服务器,服务器再推送给用户B,在单机系统上所有的用户都和同一个服务器建立连接,所有的session都存储在同一个服务器中。

但随着用户数量的增加,我们需要将应用程序扩展为WebSocket集群,以提供更好的性能和可伸缩性。

集群场景

当演变为集群环境后,用户A与节点1建立连接,用户B与节点2建立连接,用户A发送一条消息到服务器,服务器无法再推送用户B

在WebSocket集群中,一个常见的问题是连接状态同步。当一个节点接收到客户端的连接请求并与其建立WebSocket连接时,其他节点也需要了解这个连接的存在。这样,当其他节点收到消息时,它们可以将消息正确地推送给与该客户端相关联的节点。

然而,如果连接状态同步存在问题,可能会导致消息发送错误或丢失。例如,在一个WebSocket集群中,当一个客户端连接到节点A时,而其他节点(B、C)不知道这个连接存在,当节点B收到一条消息并尝试将其推送给该客户端时,它会失败,因为它不知道该客户端连接到了节点A。

这种情况下,客户端可能会错过重要的消息或者体验不一致的消息推送。此外,如果客户端断开连接时,各个节点的连接状态同步也是至关重要的。如果某个节点仍然认为客户端处于活动状态,而实际上该客户端已经断开连接,节点可能会继续尝试将消息推送给它,从而浪费资源和带宽。

为了解决这个问题,需要在集群中实现连接状态的一致性和同步机制,以确保消息能够正确地传递和推送给客户端。

方案

方案一:Session共享(不可行)

在WebSocket集群中,共享Session的方法并不适用于解决连接状态同步的问题。虽然在HTTP中,可以使用共享Session来解决集群问题,例如将Session信息存储在Redis数据库中,但是在WebSocket中这种方法是不可行的。

WebSocket的Session与HTTP的Session有所不同。WebSocket的Session是与连接相关的状态,而不是像HTTP的Session那样与请求相关。WebSocket的连接在不同的服务器之间是无法共享的,因此无法将WebSocket的Session存储在共享的存储中。

换句话说Http短连接是无状态的,websocket是长链接的有状态,连接在哪个节点就在哪个节点了。

方案二:负载均衡器(状态路由)

在WebSocket集群中,使用负载均衡器进行状态路由是一种常见的解决方案。负载均衡器可以将客户端的连接请求分发到集群中的不同节点上,以实现负载均衡和高可用性。

用户A、用户B与节点1建立连接,用户C与节点2建立连接,用户A发送一条消息到服务器,服务器再推送给用户B

固定参数哈希(Fixed Parameter Hashing): 这种策略是根据请求中的特定参数(例如会议ID)进行哈希计算,然后将相同哈希结果的请求路由到同一节点上。这样可以确保同一会话或同一组相关连接始终被路由到同一个节点上。这种方法的优点是保持了连接的一致性,缺点会导致节点负载不均衡,因为某些参数值可能会导致较大的连接集中在某些节点上。

下面是一个示例的Nginx配置,展示了如何使用固定参数哈希进行WebSocket连接的负载均衡:

http {upstream websocket_backend {hash $arg_meeting_id consistent;server backend1.example.com:8080;server backend2.example.com:8080;server backend3.example.com:8080;}server {listen 80;location /websocket {proxy_pass http://websocket_backend;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";}}
}

方案三:广播机制(异步方式 - 建议)

在集群中的每个服务节点上发送群发消息,以确保消息能够覆盖到所有连接的客户端。可以通过使用消息队列或广播协议来实现该机制。然而,需要注意的是广播机制可能会增加网络负载和处理成本

为了解决发送方和接收方必须在同一个服务器下才能发送消息的限制,可以采用消息广播的方式将消息通知给所有的服务器。这可以通过使用消息中间件的发布订阅模式来实现。通过将消息发送到中间件,然后再将消息广播给订阅的服务器,类似于广播的方式,只要订阅了消息,就能接收到消息的通知。

具体实现方式可以使用以下两种方式之一:

  1. Redis的发布订阅(Pub/Sub):使用Redis作为消息中间件,发布者将消息发布到特定的频道,而订阅者会订阅该频道,从而接收到消息的通知。
  2. 消息队列的广播:使用支持广播功能的消息队列,如RabbitMQ或Apache Kafka。发布者将消息发送到消息队列的特定主题(topic),而所有订阅了该主题的消费者都能接收到消息。

以上方案都将消息的发送和接收解耦,并通过消息中间件来实现跨服务器的消息广播。这样,无论连接的客户端分布在哪个服务器上,都能够接收到广播的消息。

方案四:路由转发(同步方式)

在WebSocket集群中,可以采用路由转发的方式来处理群发消息。该方案的核心思想是在集群的每个服务节点上维护一个路由表(查不到时去redis查),记录连接的客户端和对应的服务节点。当发消息时,根据路由表将消息转发到对应的服务节点,由该节点负责将消息发送给连接的客户端。

具体实现该方案需要以下步骤:

  1. 连接路由表:每个服务节点维护一个连接路由表,用于记录客户端连接的信息,包括客户端标识(如客户端ID)和对应的服务节点(查不到时去redis查)。
  2. 路由协议:实现一个路由协议,用于在集群中的各个服务节点之间传递路由信息和消息(用Http协议或者用websocket协议模拟一个客户端都行)。
  3. 路由转发:当需要发消息时,消息发送方的服务节点根据路由表确定每个连接的客户端所在的服务节点,并将消息转发给对应的服务节点。
  4. 消息发送:接收到转发的消息的服务节点负责将消息发送给连接的客户端,确保消息能够到达每个客户端。

通过路由转发方案,可以将群发消息的负载分散到各个服务节点上,避免了单个节点处理大量消息的压力。同时,该方案也能够确保消息能够正确路由和转发到每个连接的客户端。

方案五:高可用(多活冗余)

在WebSocket集群中,可以采用高可用多活冗余方案来提高系统的可用性和容错性。该方案的核心思想是将多台服务器同时工作,并允许客户端同时连接到多台服务器。当需要发送消息时,每台服务器都将消息发送给连接到它的客户端。

具体实现该方案的步骤如下:

  1. 多台服务器:配置多台服务器,每台服务器都运行相同的应用程序,形成一个集群。这些服务器可以位于不同的物理位置或云服务商上。
  2. 客户端连接多台服务器,每个客户端就可以同时与多台服务器建立连接。
  3. 消息发送:当需要发送消息时,每个服务器都将消息发送给连接到它的客户端。这意味着每个服务器都需要维护自己的连接列表,并向连接的客户端发送消息。
  4. 容错处理:如果某台服务器出现故障或断开连接,其他服务器仍然可以继续发送消息给客户端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/3461.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

量子力学的起源和基本概念

亲爱的读者, 欢迎回到我们的量子力学系列文章。在我们的第一篇文章中,我们进行了量子力学的总体介绍。今天,我们将深入探讨量子力学的起源和一些基本概念。 量子力学的起源可以追溯到20世纪初,当时的科学家们遇到了一些古典物理…

【Java用法】windows10系统下修改jar中的文件并重新打包成jar文件然后运行

windows10系统下修改jar中的文件并重新打包成jar文件然后运行 一、背景描述二、操作步骤2.1 解压jar包2.2 修改配置文件2.3 重新打成jar包2.4 确认是否修改成功2.5 运行程序 一、背景描述 测试环境(Linux)的代码(jar包)拉取到本地…

Java之集合Collection

Collection接口有两个子接口:List(链表|线性表)和Set(集) ---|Collection: 单列集合---|List: 有存储顺序, 可重复---|ArrayList: 数组实现, 查找快, 增删慢由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以…

【深度学习 | CNN】“深入解析卷积神经网络与反卷积:从原理到应用的全面指南” (从一维、二维、三维讲解)

🤵‍♂️ 个人主页: @AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍 🙋‍♂️声明:本人目前大学就读于大二,研究兴趣方向人工智能&硬件(虽然硬件还没开始玩…

设计模式3:单例模式:JMM与volatile和synchronized的关系

本文目录 JMM简介Java 内部内存模型(The Internal Java Memory Model)硬件内存架构(Hardware Memory Architecture)弥合 Java 内存模型和硬件内存架构之间的差距(Bridging The Gap Between The Java Memory Model And The Hardware Memory Architecture)1.共享对象的可见性2.竞…

微软公布量子超级计算机路线图

光子盒研究院 6月22日,微软公布了三个重要的量子计算公告。首先,公司宣布它已经实现了通往量子超级计算机的六步路线图的第一个里程碑,并发表了一篇经同行评议的研究论文来证明这一成就。 这家科技巨头的第二项公告是将其人工智能&#xff08…

代理服务器之 squid、lvs、nginx、haproxy之间的区别

代理服务器之 squid、lvs、nginx、haproxy之间的区别 代理服务可简单的分为正向代理和反向代理 1、正向代理 正向代理服务器:squid 用于代理内部网络对 Internet 的连接请求(如 VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标 Web 服务器的 HT…

Spring Resources资源操作

文章目录 1、Spring Resources概述2、Resource接口3、Resource的实现类3.1、UrlResource访问网络资源3.2、ClassPathResource 访问类路径下资源3.3、FileSystemResource 访问文件系统资源3.4、ServletContextResource3.5、InputStreamResource3.6、ByteArrayResource 4、Resour…

Keil MDK编程环境下的 STM32 IAP下载(学习笔记)

IAP的引入 不同的程序下载方式 ICP ICP(In Circuit Programing)。在电路编程,可通过 CPU 的 Debug Access Port 烧录代码,比如 ARM Cortex 的 Debug Interface 主要是 SWD(Serial Wire Debug) 或 JTAG(Joint Test Action Group); ISP ISP(I…

PostgreSQL处理JSON数据

源:https://blog.csdn.net/c_zyer/article/details/130968257?ops_request_misc&request_id&biz_id102&utm_termPostgreSQL%20%E7%9A%84JSON%20%E5%A4%84%E7%90%86&utm_mediumdistribute.pc_search_result.none-task-blog-2allsobaiduweb~default-…

Mysql找出执行慢的SQL【慢查询日志使用与分析】

分析慢SQL的步骤 慢查询的开启并捕获:开启慢查询日志,设置阈值,比如超过5秒钟的就是慢SQL,至少跑1天,看看生产的慢SQL情况,并将它抓取出来explain 慢SQL分析show Profile。(比explain还要详细…

LeetCoda 打卡day53--动态规划之最长子序列

一个人的朝圣 — LeetCode打卡第52天 知识总结 Leetcode 1143. 最长公共子序列题目说明代码说明 Leetcode 53. 最大子数组和题目说明代码说明 Leetcode 1035. 不相交的线题目说明代码说明 知识总结 今天几道最长子序列的题目, 都可以用一个固定的模版完成. 理解其中递推公式的…