WebSocket在分布式环境中的局限性及解决方案
WebSocket 在分布式环境中存在一些局限性,特别是当系统需要扩展多个服务实例时,单个 WebSocket 连接的管理和消息推送就变得比较复杂。因此,必须采取一些额外的措施来确保 WebSocket 能在多个服务实例之间正确工作。
WebSocket 在分布式环境中的局限性
-
单实例限制:传统的 WebSocket 连接是基于单一实例的,如果我们的应用扩展了多个实例,每个实例只能管理它自己建立的 WebSocket 连接,导致消息无法从一个实例推送到另一个实例的连接中。
-
消息同步问题:当多个实例都需要处理来自 Kafka 或其他消息队列的事件时,如果不采取措施,消息可能无法同步推送到所有 WebSocket 连接。比如,如果某个服务实例处理了 Kafka 消息,可能无法将消息推送到所有其他实例的 WebSocket 连接。
示例:在线聊天应用
假设我们正在开发一个 在线聊天应用,该应用有多个用户(客户端)同时在线,每个用户通过 WebSocket 与聊天服务器进行连接,实时接收和发送消息。
场景描述:
- 用户 A 和 用户 B 都使用浏览器登录这个聊天应用。
- 服务器 会管理每个用户与浏览器之间的 WebSocket 连接,并保持这些连接持续开放,实时推送消息。
- 由于 服务器 可能分布在多个 实例 上(例如 服务器实例 1 和 服务器实例 2),因此,每个服务器实例只会管理与其连接的 用户。
设定:
- 服务器实例 1 管理了 用户 A 的 WebSocket 连接。
- 服务器实例 2 管理了 用户 B 的 WebSocket 连接。
发生的情况:
1. 用户 A 向用户 B 发送消息:
- 用户 A 在聊天框中输入消息并点击发送。
- 服务器实例 1 接收到 用户 A 的消息。
- 服务器实例 1 将消息推送到 用户 B,但它并不知道 用户 B 连接在 服务器实例 2 上,因此,它不能直接将消息推送给 用户 B。
2. 问题:
- 服务器实例 1 无法直接推送消息给 服务器实例 2 上的 用户 B,因为 WebSocket 是一个点对点的连接协议,每个服务器实例只能与它自己管理的 WebSocket 连接进行通信。
- 用户 A 的消息只能通过 服务器实例 1 发送给 用户 A,而不能跨实例推送给 用户 B。
解决方案:使用消息队列(如 Redis)
为了解决这个问题,我们可以使用 消息队列(例如 Redis)来 同步跨实例的消息。
- 服务器实例 1 将 用户 A 的消息发布到 Redis 的一个 频道,比如频道名为
chat-channel。 - 服务器实例 2 订阅了
chat-channel这个频道,当 服务器实例 1 发布消息时,服务器实例 2 会收到消息。 - 服务器实例 2 收到消息后,推送该消息给它管理的 用户 B。
简化的流程:
- 用户 A 向 用户 B 发送消息 -> 服务器实例 1 处理。
- 服务器实例 1 将消息发布到 Redis 的
chat-channel。 - 服务器实例 2 订阅
chat-channel,接收到消息。 - 服务器实例 2 将消息推送给 用户 B。
总结
- 在 WebSocket 的传统实现中,每个 服务器实例 管理自己的 WebSocket 连接,不能直接跨实例推送消息。
- 通过 Redis 或 Kafka 等消息队列,服务器实例 可以将消息发布到共享频道,其他实例可以订阅并接收到该消息。
- 通过这种方式,即使 用户 A 在 服务器实例 1,而 用户 B 在 服务器实例 2,也能确保消息能够实时推送到 用户 B。
解决方案:使用 消息中间件 与 分布式 WebSocket 管理
为了解决 WebSocket 在分布式环境中的问题,我们可以使用 消息中间件(如 Kafka、RabbitMQ、Redis 等)来同步消息,并结合 分布式 WebSocket 管理 来保证每个 WebSocket 客户端能够接收到消息。
1. 使用 Redis 作为消息代理
- Redis 是一个支持 发布/订阅(Pub/Sub)机制的高效内存数据存储服务,适用于多实例之间的消息同步。
- 我们可以利用 Redis 的 发布/订阅 模式来广播 WebSocket 消息,将消息推送到所有连接的 WebSocket 客户端。
- 在每个 WebSocket 实例中,客户端连接后都会订阅 Redis 中的某个频道,当消息发布到该频道时,Redis 会将消息转发给所有订阅了该频道的实例,从而实现多实例间的 WebSocket 消息推送。
2. 方案设计
- Kafka 消费者:在后台,Kafka 消费者服务从消息队列中消费到的事件(如工单拒绝事件)会通过 Redis 发布 消息。
- WebSocket 服务:每个 WebSocket 服务实例会订阅 Redis 中的特定频道,当 Kafka 消费者发布消息时,Redis 会将消息广播给所有订阅了该频道的 WebSocket 实例,从而向所有客户端推送消息。
3. 总结
- WebSocket 连接:每个 WebSocket 服务实例会订阅 Redis 中的消息频道,确保多个服务实例能够接收到相同的推送消息。
- Kafka 消费者:从 Kafka 消费事件后,发布到 Redis 消息频道,确保消息的同步。
- Redis Pub/Sub:Redis 的发布/订阅机制实现了跨服务实例的消息同步,解决了多实例间 WebSocket 消息推送的挑战。
4. 优点
- 高可扩展性:利用 Redis 或其他消息中间件,能够在多个服务实例之间同步消息,解决了 WebSocket 在分布式环境中的限制。
- 解耦:消息推送和 WebSocket 连接的管理解耦,减少了直接依赖,提高了系统的灵活性和维护性。
- 实时推送:WebSocket 与 Redis 集成可以实现实时的消息推送,确保管理员能够即时收到任务拒绝或其他工单相关的通知。
这样,使用 Redis 和 WebSocket 的组合解决方案能够有效克服 WebSocket 在分布式环境中的局限性,并提供一个高效、可扩展的消息推送机制。
相关文章:
WebSocket在分布式环境中的局限性及解决方案
WebSocket 在分布式环境中存在一些局限性,特别是当系统需要扩展多个服务实例时,单个 WebSocket 连接的管理和消息推送就变得比较复杂。因此,必须采取一些额外的措施来确保 WebSocket 能在多个服务实例之间正确工作。 WebSocket 在分布式环境…...
SIM盾构建安全底座的可行性分析
一、背景 1.1安全需求现状 在数字化时代,信息安全面临着日益严峻的挑战。各类网络攻击手段层出不穷,如数据泄露、恶意软件攻击、网络诈骗等,给个人、企业和社会带来了巨大的损失。为了保障信息系统的安全性,需要构建一个可靠的安…...
【Java八股文】10-数据结构与算法面试篇
【Java八股文】10-数据结构与算法面试篇 数据结构与算法面试题数据结构红黑树说一下跳表说一下?LRU是什么?如何实现?布隆过滤器怎么设计?时间复杂度? 排序算法排序算法及空间复杂度 数据结构与算法面试题 数据结构 红…...
go 并发 gorouting chan channel select Mutex sync.One
goroutine // head: 前缀 index:是一个int的指针 func print(head string, index *int) {for i : 0; i < 5; i {// 指针对应的int *indexfmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)} }/* Go 允许使用 go 语句开启一个新的运…...
亲测Windows部署Ollama+WebUI可视化
一. Ollama下载 登录Ollama官网(Ollama)点击Download进行下载 如果下载很慢可用以下地址下载: https://github.com/ollama/ollama/releases/download/v0.5.7/OllamaSetup.exe 在DeepSeek官网上,你可以直接点击【model】 到达这个界面之后,…...
linux 安装启动zookeeper全过程及遇到的坑
1、下载安装zookeeper 参考文章:https://blog.csdn.net/weixin_48887095/article/details/132397448 2、启动失败 1、启动失败JAVA_HOME is not set and java could not be found in PATH 已安装 JAVA 配置了JAVA_HOME,还是报错解决方法:参考…...
策略模式Spring框架下开发实例
策略类Spring框架下开发实例 先列出策略模式下需要那些类: 策略接口 (Strategy),定义所有策略类必须遵循的行为。 具体策略类(如 ConcreteStrategyA、ConcreteStrategyB),实现不同的算法或行为。 上下文类 (Context),…...
DeepSeek模型量化
技术背景 大语言模型(Large Language Model,LLM),可以通过量化(Quantization)操作来节约内存/显存的使用,并且降低了通讯开销,进而达到加速模型推理的效果。常见的就是把Float16的浮…...
【练习】【回溯:组合:不同集合】力扣 17. 电话号码的字母组合
题目 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits “2…...
分布式文件系统HDFS
一、HDFS简介 HDFS( Hadoop Distributed File System ),意为:Hadoop分布式文件系统。是Apache Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。分布式文件系统解决大数据如何存储问题。分布式意味…...
从WebRTC到EasyRTC:嵌入式适配的视频通话SDK实现低延迟、高稳定性音视频通信
WebRTC最初是为浏览器之间的实时通信设计的,其资源需求和复杂性可能对嵌入式设备的性能提出较高要求,因此在嵌入式系统中应用时面临一些挑战: 1)资源消耗较高 CPU和内存占用:WebRTC是一个功能强大的实时通信框架&…...
WordPress自定义排序插件:Simple Custom Post Order完全指南(SEO优化版)
在WordPress建站中,文章、分类目录或页面的默认排序方式往往无法满足个性化需求。WordPress自定义排序插件:Simple Custom Post Order插件,你可以轻松实现拖拽式自定义排序,无需修改代码即可优化内容展示逻辑。本文将详细介绍这款…...
docker安装ros2 并在windows中显示docker内ubuntu系统窗口并且vscode编程
这里包括docker desktop安装ros2 humble hawkshill , 安装xserver(用来在windows中显示ubuntu中窗口), vscode安装插件连接docker并配置python的一系列方法 1.安装xserver 为了能方便的在windows中显示ubuntu内的窗口,比如rqt窗口 参考文章:https://www.cnblogs.com/larva-zhh…...
【QT中的一些高级数据结构,持续更新中...】
QT中有一些很精妙、便捷的设计,在了解这些数据的同时,我们可以学到如何更好的设计代码。本贴持续更新中,欢迎关注和收藏 一 QScopedPointer主要特点:示例代码 二 Q_DISABLE_COPY 一 QScopedPointer QScopedPointer 是 Qt 中的一种…...
简单工厂模式 (Simple Factory Pattern) 在Spring Boot 中的应用
简单工厂模式(Simple Factory Pattern)虽然不属于 GoF 23 种经典设计模式,但在实际开发中非常常用,尤其是在 Spring Boot 项目中。它提供了一种简单的方式来创建对象,将对象的创建逻辑集中到一个工厂类中。 一、简单工…...
《95015网络安全应急响应分析报告(2024)》
2025年2月,95015服务平台发布了最新一期的《95015网络安全应急响应分析报告(2024)》。报告分别从整体形势、受害者特征、攻击者特征等方面,对2024年95015平台接报的739起网络安全应急响应事件展开分析,并给出了7个年度…...
TensorFlow v2.16 Overview
TensorFlow v2.16 Overview 一、模块 Modules二、类 Classes三、函数 Functions TensorFlow v2.16.1 Overview 一、模块 Modules 模块是TensorFlow中组织代码的一种方式,将相关的功能和类封装在一起,方便用户使用和管理。每个模块都提供了特定领域的公共…...
Udp发送和接收数据(python和QT)
服务端代码 (python) import socketdef udp_server(host0.0.0.0, port12345):# 创建一个UDP套接字sock socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定服务器的IP地址和端口号sock.bind((host, port))print(f"UDP服务器已启动,监听端口 {port}...&…...
element-plus 根据条件显示多选框
代码如下: <el-table :data"pager.lists" selection-change"handleSelectionChange" row-key"id" :tree-props"{ checkStrictly: true }" :cell-class-name"cellClass"> <el-table-column type"s…...
Ubuntu 22.04 Install deepseek
前言 deepseekAI助手。它具有聊天机器人功能,可以与用户进行自然语言交互,回答问题、提供建议和帮助解决问题。DeepSeek 的特点包括: 强大的语言理解能力:能够理解和生成自然语言,与用户进行流畅的对话。多领域知识&…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
