当前位置: 首页 > news >正文

单体架构 IM 系统之 Server 节点状态化分析

基于 http 短轮询模式的单体架构的 IM 系统见下图,即客户端通过 http 周期性地轮询访问 server 实现消息的即时通讯,也就是我们前面提到的 “信箱模型”。“信箱模型” 虽然实现非常容易,但是消息的实时性不高。

我们在上一篇文章(单体架构 IM 系统之长轮询方案设计)中提出了优化方案,即通过 http 长轮询方式模拟出长连接的效果。

基于 http 长轮询方式实现的 IM 系统的单体架构中, server 节点还是无状态化的吗?所谓 “无状态化” 节点,是指进程在内存和硬盘中没有独立的数据;很明显,不同的 server 节点会 hold 住不同客户端的 http 请求,也就是不同的 server 节点中会存储不同客户端的数据, server 节点是有状态化的;此时,点对点的消息发送逻辑肯定需要进行调整。

大家可以先思考几个问题:

  1. 在 http 长轮询模式下, server 节点是有状态的,如何实现 server 节点的高可用呢?

  2. 客户端 x 发消息给 y,如果 x 和 y 访问的是不同的 server 节点,应该如何处理呢?

  3. 在 http 长轮询模式下,怎样判断消息接收方是否在线呢?

我们直接给出在 http 长轮询模式下,消息点对点的发送流程;以客户端 x 发消息给客户端 y 为例,如下:

  • 客户端 x 向 server 端发送 http 消息请求;

  • server 首先将消息直接落库,分别写 “云消息表” 和 “离线表”;

  • 然后 server 访问缓存,获取消息接收方 y 的在线状态,若 y 不在线,则整个流程结束;

  • 如果消息接收方 y 在线,通过访问缓存获取 y 连接的是哪一个 server 节点;

  • 如果 y 和 x 连接的同一个 server 节点,则 server 将该消息通过 http 长轮询返回给客户端 y;

  • 如果 y 连接的是另一个 server 节点,此时需要当前 server节点将消息推送到目标 server 节点;

  • 最后目标 server 节点将消息通过 http 长轮询返回给客户端 y。

在上述流程中,有两个地方需要特别注意:

  1. 客户端每一次发起 http 长轮询请求,相当于一次心跳,表示用户的在线状态,需要在缓存中记录客户端的在线数据;在 http 短轮询模式中,缓存中记录的 session 数据是 map<uid, {type, cmd, time}> ,在 http 长轮询模式中,需要记录客户端请求的是哪一个 server 节点,所以 session 类型为 map<uid, {type, cmd, time, serverip}>。

  2. 不管消息接收方在线与否,server 节点接收消息后,都需要写 “离线表”,这样设计的原因是为了提高消息的可靠性;因为即使用户 “在线”,在 http 长轮询返回时,客户端有可能接收不到消息,同时,在一次完整的 http 长轮询请求的间隙中,消息都是有丢失的可能的,所以持久化 “离线表” 是可靠性的保证;因此,在每一次 http 长轮询请求中,都需要访问 “离线表”,一是删除客户端已经收到的消息,二是从 “离线表” 中获取还未收到的消息。

在 http 长轮询模式下, server 节点是有状态的,那么其高可用如何保证呢?这个问题很容易解决:首先 server 节点肯定要集群化部署,然后由 反向代理 nginx 转发请求到 server ; nginx 通过配置实现客户端ip的会话保持,即将相同的客户端请求始终转发到固定的 server 节点; 当 server 节点挂掉之后,nginx 将请求转发到其他 server 节点即可,服务仍将持续提供,只需变更缓存中客户端状态信息即可。

单体架构 IM 系统,从架构到设计,从协议到逻辑,其关键点都进行了 一 一 分析;最后,我们简单聊一下 server 的整体设计,server 通过 Go语言进行了实现,见下图。

  1. 主协程,不处理任何的业务逻辑,用于接收外部信号,如关闭程序等;

  2. 子协程,用于接收客户端连接,针对每一个客户端连接,子协程都会生成两个协程来维护该连接,即:每一条连接会有一个独立的协程组来维护(该协程组中有两个协程,一个用于读,一个用于写);

  3. 连接管理器,实现对所有连接的管理,从连接中读取请求交由业务逻辑模块处理;

  4. 业务逻辑模块,实现核心的业务逻辑,包括:登录、登出、心跳、发消息等;

  5. 在线用户管理器,维护连接当前 server 节点所有的客户端;如果消息接收方在当前 server 节点,在线用户管理器通过 管道(chan)将消息传输给连接管理器中消息接收方的连接;

  6. 通讯协议,是公共协议定义,由【连接管理器】【业务逻辑模块】【在线用户管理器】共同引用。

关于 “每一条连接会有一个独立的协程组来维护”,是 Go 语言通用的高效网络编程模型,见下图。

  • 客户端与服务端建立连接时,在服务端其实创建了一个 socket (即 fd 或句柄);

  • 然后为该 socket 生成一个协作组,该协程组包括两个协程: 协程1-1,负责对 socket 进行读; 协程1-2,负责对 socket 进行写;这两个协程,一个读一个写互不影响,高效协作;

  • 当需要向客户端写消息时,不管是当前socket 请求的数据,还是从其他 socket 中读取的数据,必须通过协程组的管道(channel) 作为入口,然后协程1-2会从 channel 中读取数据然后写入到 socket 中。

最后,总结文中关键:

1、基于 http 长轮询方式实现的 IM 系统的单体架构中, server 节点是有状态的;

2、基于 http 长轮询发消息流程:消息到达 serer 后,先落库;若消息接收方在当前 server 节点,直接返回,否则需要将消息推送到目标 server 节点;

3、 基于 http 长轮询方式实现的 IM 系统,缓存中需要记录客户端连接的是哪一个 server 节点;

4、 在 http 长轮询模式中,不管消息接收方在线与否,server 节点接收消息后,都需要写 “离线表”;

5、 Go 语言通用的高效网络编程模型:每一条连接会有一个独立的协程组来维护;协程1-1,负责对 socket 进行读; 协程1-2,负责对 socket 进行写。

至此,“单体架构 IM 系统” 核心问题全部讲完了,你是否还记得如下关键点:

为什么要采用单体架构?

单体架构有怎样的优势?

单体架构的IM系统是怎样的?

单体架构 IM 系统的消息收发逻辑是如何实现的?

什么是 “信箱模型” ,有什么优势和缺点?

“信箱模型” 消息的实时性如何提升?

http 长轮询方式的两种落地方案:“定时器” 和 “时间轮” 如何实现?

上述问题都可从以下四篇文章中找到答案:

《单体架构 IM 系统之架构设计》

《单体架构 IM 系统之核心业务工作实现》

《单体架构 IM 系统之长轮询方案设计》

《单体架构 IM 系统之 Server 节点状态化分析》

分层架构 IM 系统的关键问题,后续文章马上更新跟进......

相关文章:

单体架构 IM 系统之 Server 节点状态化分析

基于 http 短轮询模式的单体架构的 IM 系统见下图&#xff0c;即客户端通过 http 周期性地轮询访问 server 实现消息的即时通讯&#xff0c;也就是我们前面提到的 “信箱模型”。“信箱模型” 虽然实现非常容易&#xff0c;但是消息的实时性不高。 我们在上一篇文章&#xff08…...

java xml 文本解析

示例文本 <Message><MessageName>time_request</MessageName><Timestamp>20220217165432906359</Timestamp><Body><EQPID>CMMAB01-DTP01</EQPID></Body> </Message>示例代码 import org.w3c.dom.Document; impo…...

Docker占用空间太大磁盘空间不足清理妙招

docker占用空间太大了&#xff0c;磁盘空间不足&#xff0c;清理3妙招 清除所有已停止的容器&#xff08;container&#xff09;、未被任何容器所使用的卷&#xff08;volume&#xff09;、未被任何容器所关联的网络&#xff08;network&#xff09;、所有悬空镜像&#xff08…...

编程之路,从0开始:字符函数和字符串函数

Hello大家好&#xff01;很高兴我们又见面了&#xff01; 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 目录 1、字符分类函数 2、字符转换函数 3、字符串函数 1、 strcpy 2、 strcat 3、 strcmp 4、strlen(s) 5、strstr(s1, s2) 6、 strtok(s1, s2…...

化工防爆巡检机器人:在挑战中成长,为化工安全保驾护航

随着全球能源需求的不断攀升&#xff0c;化工行业的安全性与高效性愈发受到关注。化工设施规模巨大&#xff0c;而且其中多数存在高风险因素&#xff0c;像是易燃易爆化学物质、高温环境、有毒有害物质以及高压设备等。仅2023年&#xff0c;国内危化品事故就多达652起&#xff…...

音频采样数据格式

音频信号在模拟到数字转换时&#xff0c;会涉及到多个关键参数&#xff0c;如采样率、位深度、通道数等。下面是常见的音频采样数据格式及其相关概念&#xff1a; 1. 采样率 (Sample Rate) 采样率指的是每秒钟对音频信号进行采样的次数&#xff0c;单位为赫兹 (Hz)。常见的值…...

【pytorch】常用强化学习算法实现(持续更新)

持续更新常用的强化学习算法&#xff0c;采用单python文件实现&#xff0c;简单易读 2024.11.09 更新&#xff1a;PPO(GAE); SAC2024.11.12 更新&#xff1a;OptionCritic(PPOC) "PPO" import copy import time import torch import numpy as np import torch.nn as …...

DAY59||并查集理论基础 |寻找存在的路径

并查集理论基础 并查集主要有两个功能&#xff1a; 将两个元素添加到一个集合中。判断两个元素在不在同一个集合 代码模板 int n 1005; // n根据题目中节点数量而定&#xff0c;一般比节点数量大一点就好 vector<int> father vector<int> (n, 0); // C里的一…...

Mybatis执行自定义SQL并使用PageHelper进行分页

Mybatis执行自定义SQL并使用PageHelper进行分页 基于Mybatis&#xff0c;让程序可以执行动态传入的SQL&#xff0c;而不需要在xml或者Select语句中定义。 代码示例 pom.xml 依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId&g…...

OpenCV DNN

OpenCV DNN 和 PyTorch 都是常用的深度学习框架&#xff0c;但它们的定位、使用场景和功能有所不同。让我们来对比一下这两个工具&#xff1a; 1. 框架和功能 OpenCV DNN&#xff1a;OpenCV DNN 模块主要用于加载和运行已经训练好的深度学习模型&#xff0c;支持多种深度学习…...

什么时候需要复写hashcode()和compartTo方法

在Java编程中&#xff0c;复写&#xff08;重写&#xff09;hashCode()和compareTo()方法的需求通常与对象的比较逻辑和哈希集合的使用紧密相关。但请注意&#xff0c;您提到的compartTo可能是一个拼写错误&#xff0c;正确的方法名是compareTo()。以下是关于何时需要复写这两个…...

PostgreSQL 日志文件备份

随着信息安全的建设&#xff0c;在三级等保要求中&#xff0c;要求日志至少保留半年 180 天以上。那么 PostgreSQL 如何实现这一要求呢。 我们需要配置一个定时任务&#xff0c;定时的将数据库日志 log 下的文件按照生成的规则将超过一定时间的日志拷贝到其它的路径下&#xf…...

2023年MathorCup数学建模B题城市轨道交通列车时刻表优化问题解题全过程文档加程序

2023年第十三届MathorCup高校数学建模挑战赛 B题 城市轨道交通列车时刻表优化问题 原题再现&#xff1a; 列车时刻表优化问题是轨道交通领域行车组织方式的经典问题之一。列车时刻表规定了列车在每个车站的到达和出发&#xff08;或通过&#xff09;时刻&#xff0c;其在实际…...

数字农业产业链整体建设方案

1. 引言 数字农业产业链整体建设方案旨在通过数字化手段提升农业产业效率与质量&#xff0c;推动农业现代化进程。方案聚焦于资源数字化、产业数字化、全局可视化与决策智能化的实现&#xff0c;构建农业产业互联网平台&#xff0c;促进农业全流程、全产业链线上一体化发展。 …...

awk那些事儿:在awk中使用shell变量的两种方式

awk是Linux中一款非常好用的程序&#xff0c;可以逐行处理文件&#xff0c;并提供了强大的语法和函数&#xff0c;和grep、sed一起被称为“Linux三剑客”。 在使用awk处理文件时&#xff0c;有时会用到shell中定义的变量&#xff0c;由于在shell中变量的调用方式是通过$符号进…...

大数据面试题--kafka夺命连环问(后10问)

目录 16、kafka是如何做到高效读写&#xff1f; 17、Kafka集群中数据的存储是按照什么方式存储的&#xff1f; 18、kafka中是如何快速定位到一个offset的。 19、简述kafka中的数据清理策略。 20、消费者组和分区数之间的关系是怎样的&#xff1f; 21、kafka如何知道哪个消…...

智能量化交易的多样化策略与风险控制:中阳模型的应用与发展

随着金融市场的不断创新与发展&#xff0c;智能量化交易正逐渐成为金融投资的重要手段。中阳智能量化交易模型通过技术优势、策略优化与实时风险控制等多方面结合&#xff0c;为投资者提供了强有力的工具支持。本文将对中阳量化模型的技术细节、多策略组合与市场适应性进行深入…...

小皮PHP连接数据库提示could not find driver

最近遇到一个奇怪的问题&#xff0c;我的小皮上安装的8.0.2版本的php连接数据库正常。下载使用8.2.9时&#xff0c;没有php.ini,把php-development.ini改成 php.ini后&#xff0c;就提示could not find driver。 网上查了说把php.ini里的这几个配置打开&#xff0c;我也打开了&…...

2024.11.13(一维数组相关)

思维导图 1> 提示并输入一个字符串&#xff0c;统计该字符串中大写字母、小写字母、数字字符、空格字符的个数并输出 2> 提示并输入一个字符串&#xff0c;将该字符串中的所有字母挑选到一个新数组中&#xff0c;将所有的数字字符挑选到另一个新数组中。并且将数字字符对…...

豆包MarsCode算法题:数组元素之和最小化

数组元素之和最小化 问题描述思路分析分析思路解决方案 参考代码&#xff08;Python&#xff09;代码分析1. solution 函数2. 计算 1 2 3 ... n 的和3. 乘以 k 得到最终的数组元素之和4. 主程序&#xff08;if __name__ __main__:&#xff09;代码的时间复杂度分析&#x…...

Hbase Shell

一、启动运行HBase 首先登陆SSH&#xff0c;由于之前在Hadoop的安装和使用中已经设置了无密码登录&#xff0c;因此这里不需要密码。然后&#xff0c;切换至/usr/local/hadoop&#xff0c;启动Hadoop&#xff0c;让HDFS进入运行状态&#xff0c;从而可以为HBase存储数据&#…...

激活函数解析:神经网络背后的“驱动力”

神经网络中的激活函数&#xff08;Activation Function&#xff09;是其运作的核心组件之一&#xff0c;它们决定了神经元如何根据输入信号进行“激活”&#xff0c;进而影响整个模型的表现。理解激活函数的工作原理对于设计和优化神经网络至关重要。本篇博客将深入浅出地介绍各…...

【开源免费】基于SpringBoot+Vue.JS水果购物网站(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 065 &#xff0c;文末自助获取源码 \color{red}{T065&#xff0c;文末自助获取源码} T065&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...

推荐一款多物理场模拟仿真软件:STAR-CCM+

Siemens STAR-CCM是一款功能强大的计算流体力学(CFD)软件&#xff0c;由西门子公司推出。它集成了现代软件工程技术、先进的连续介质力学数值技术和卓越的设计&#xff0c;为工程师提供了一个全面的多物理场仿真平台。主要特点与优势&#xff1a;多物理场仿真、自动化与高效、高…...

React Hooks在现代前端开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 React Hooks在现代前端开发中的应用 React Hooks在现代前端开发中的应用 React Hooks在现代前端开发中的应用 引言 React Hooks …...

重学SpringBoot3-整合Quartz定时任务

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ Quartz 是一个开源的任务调度框架&#xff0c;用于在应用程序中创建、管理和调度定时任务。将 Quartz 和 Spring Boot 3 结合&#xff0c;可以轻松实现定时任务的灵活管理…...

STM32单片机WIFI语音识别智能衣柜除湿消毒照明

实践制作DIY- GC0196-WIFI语音识别智能衣柜 一、功能说明&#xff1a; 基于STM32单片机设计-WIFI语音识别智能衣柜 二、功能介绍&#xff1a; STM32F103C系列最小系统板LCD1602显示器ULN2003控制的步进电机&#xff08;柜门开关&#xff09;5V加热片直流风扇紫外消毒灯DHT11…...

spring中entity的作用

在Spring框架中&#xff0c;特别是结合Spring Data JPA&#xff08;Java Persistence API&#xff09;时&#xff0c;Entity类用于表示数据库中的表。这些类通常用于ORM&#xff08;对象关系映射&#xff09;&#xff0c;即将对象模型与关系型数据库中的表进行映射。以下是Enti…...

2019年下半年试题二:论软件系统架构评估及其应用

论文库链接&#xff1a;系统架构设计师论文 论文题目 对于软件系统&#xff0c;尤其是大规模复杂软件系统而言&#xff0c;软件系统架构对于确保最终系统的质量具有十分重要的意义。在系统架构设计结束后&#xff0c;为保证架构设计的合理性、完整性和针对性&#xff0c;保证系…...

网络自动化04:python实现ACL匹配信息(主机与主机信息)

目录 背景分析代码代码解读代码总体结构1. load_pattern_from_excel 函数2. match_and_append_pattern 函数3. main 函数总结 最终的效果&#xff1a; 今天不分享netmiko&#xff0c;今天分享一个用python提升工作效率的小案例&#xff1a;acl梳理时的信息匹配。 背景 最近同事…...