尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

即时通信服务器架构的一些思考

即时通信服务器架构的一些思考
📅 发布时间:2026/7/2 2:50:05

对于一个即时通信服务器来说,在用户量少的时候,一台服务器就足以提供所有的服务。而这种架构也最简单,举个例子,用户A与用户B互为好友,A向B发消息,服务器接收到消息时,解析出接收消息的人,直接转发给B即可。可是当用户数量越来越多时,一台服务器已经无法所有用户的需求,这时就要进行服务扩容,进行分布式部署

如图所示,不同的用户可能登录到不同的服务器上,那么用户A给用户B发消息时,服务器收到消息,首先判断B是否也登录在本服务器上,如果是,那么直接转发消息即可。如果B不在本服务器上,那应该往哪里转发这条消息呢?最简单的做法就是向服务器集群中的其他服务器广播这条消息,对于每个收到这条消息的服务器,首先判断消息的目的用户是否登录在自己身上,如果不是,直接忽略该消息。如果是,那么向目的用户转发该消息。固然,这种暴力粗犷的做法是最简单直接的,但是会产生很多无效的消息转发,对于服务器性能产生很大的影响。曾看过蘑菇街开源的即时通信软件Teamtalk的代码,服务器就是这种实现方式。其服务器架构如下:

不同的msg服务器连接到同一台route server上,所有msg服务器之间的转发全部通过route server。这无疑会加重route server的负载。即时msg server部署的再多,根据木桶理论,一个系统的性能是由其最薄弱的环节所决定的。所以也注定这样的架构,其系统容量也是有限的。那么如何改善这种系统呢,很明显服务器之间的消息转发不能直接全部广播,而应该有一套明确的路由系统,即服务器在转发消息时,应该知道这条消息应该转发到哪一台服务器,这样就不需要每条消息都在所有服务器之间广播了。

那么如何实现这样一套路由系统呢?

简单的做法是,每个用户上线时,通过其连接的msg server向其他所有msg server广播自己的登录信息,告知其他服务器自己登录在哪台服务器上面。这样当某个用户向其好友发消息时,首先通过好友id查看其登录的msg server。如果好友与自己是同一台服务器,那么直接转发即可;如果不是,服务器向route server发送转发该消息,并且带上目标msg server的id.这样route server 收到消息后,解析出目标的msg server,进行一次转发即可,省去了大量的广播消息。这种方式虽然解决了广播消息的问题,但是在每台msg server上都要保存所有用户的路由信息。当所有用户都登录时,几乎就退化成了单点模型,msg server肯定承受不了。

那么如何解决这个问题呢?试想一下,既然所有的msg server上都保存着同样的路由信息,那么我们可以把这些数据从msg server剥离出来,存在一个单独的服务器上,供msg server查询。我们暂且把这个服务器叫做route info server(路由信息服务器).对于一个用户要存储的数据为

{

userid,

msgserverid

}

假设这两个数据都是32Byte,那么存储一亿个用户需要的内存32B*10^8=3.2G。目前好点的服务器都有50G的内存,很显然内存不是问题。那么就剩访问量的问题。如果所有的msg server都从这一台服务器上读取数据, 肯定会影响整个系统的性能。所以路由信息服务器不能采用这种单点模型。考虑到这种路由信息的特点,很明显是一种读多写少的数据。一个用户只有在登录的时候才会写一次路由信息,其他时候就是转发消息的时候读取路由信息了。那么可以采用类似数据库的主备模型,主服务器用来写路由信息,备服务器用于查询路由信息。而且可以设置多台备服务器,分担msg server的读压力。其实我们也可以使用一些成熟的缓存系统来完成路由信息服务器的功能,比如redis. redis拥有现成的主备方案,只是像这种通用的缓存服务器在存储数据时,消耗的内存会大些。研究过redis源码的,大多都能理解。其key value都存储在redisobject的结构体当中,有一些附加的信息,所以比自己写一个这样的服务所消耗的内存肯定会大些。

OK,说完了路由信息服务器,我们再回到msg server上来。那么msg server在转发消息时,首先根据目的用户的id 到路由信息服务器上查找其所在的msg server用于消息转发。但是这也会存在一个,每次转发消息时,都要查询一次路由信息,这无疑会影响消息的转发速度,而且也会增大路由信息服务器的访问压力。如果在发送消息之后,将路由信息保存到本地,那么下次发送消息,就无需再去路由信息服务器重复查询了。但是也不能把所有的路由全部保存到本地,那样又会严重消耗msg server的内存。于是,就有我们想到一种折中的方案,使用一个lru的缓存队列,在需要保存新的路由信息时,首先查看缓存队列是否已满,如果未满,直接插入到队首,如果队列已满,淘汰到队尾的数据。缓存列队大小可根据内存大小灵活设置。考虑到在我们平时在使用qq时,大部分人都登录着,但是发消息的人并不多。对于路由信息,在其首次转发消息是,从路由信息服务器查询一次路由,在其整个回话过程中,路由信息都缓存在本地。在其会话结束后,将最近最久未使用的路由数据淘汰出去,这种做法再考虑到内存使用的同时,又大大减少了服务器的访问次数,算是一种较好的折中方案. 在完成了路由信息系统之后,route server也可以进行水平扩展,route server要做的仅仅是转发消息,并不需要存储数据,扩展起来非常方便。最终的系统架构如下:

总结:

1. 本文所描述的即时通信服务器架构,着重讨论的是消息如何路由的问题,但这并不代表一个完整的即时通信服务器系统,诸如注册,登录,离线消息,文件等功能这些都未在本文的讨论范围之类

2. 本文中所提的方案也是一种设想,并未真正进行实现,肯定也有很多细节问题没有考虑到。欢迎大家留言讨论

相关新闻

  • Go网络开发教程
  • Kubernetes日志管理技巧
  • DAC161S997与STM32F429NI构建高精度4-20mA电流环方案

最新新闻

  • 化工设计流程与阶段解析:从可研到竣工图的全过程管理
  • AI数字员工的技术架构分层:从轻量验证到全栈私有化,怎么选?
  • Project Maven、Palantir Ontology、Gotham与AIP:从数据融合到作战流程的技术链路
  • 6DoF姿态测量:IIM-42652与PIC18F4455的硬件融合与算法优化
  • League Akari:英雄联盟玩家的智能工具箱,提升游戏体验的终极指南
  • Attention Sinks and Compression Valleys in LLMs are Two Sides of the Same Coin

日新闻

  • Python Playwright录制功能:从零到一构建自动化测试脚本
  • 如何用开源工具永久保存你心爱的小说:novel-downloader全攻略
  • In-Context Learning不是教知识,而是模式对齐:从5个示例到100个工业级样本的真相

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号