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

对于一个即时通信服务器来说,在用户量少的时候,一台服务器就足以提供所有的服务。而这种架构也最简单,举个例子,用户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. 本文中所提的方案也是一种设想,并未真正进行实现,肯定也有很多细节问题没有考虑到。欢迎大家留言讨论

3. 对于本文所提的系统,可称之为一个服务集群。而像qq这样数量用户的系统,在全国分布了很多个集群。本文所讨论的也仅仅局限于一个集群内的通信设计,而集群之间的通信又如何通信呢。每个集群的路由数据,如果全同步到其他集群,这种做法显然不是最优。如果有更好的想法,也欢迎留言讨论

时间: 11-18

即时通信服务器架构的一些思考的相关文章

关于互联网应用前端架构的一些思考

一.互联网应用的分类. 讨论前端架构之前,首先要弄清楚互联网应用的类型,明确了自己的产品所属的类型才能打造属于自己的架构.对互联网产品进行分类,网上有很多不同的观点.我觉得分类是多维度的,但是按照交互以及功能的复杂程度来分类是比较客观的.因此,我比较认同淘宝玉伯在关于前后端开发模式中对应用的分类,以下引用玉伯的观点: 前端涉及的产品形态在业界可分为两大类:Web Pages 和 Web Apps . Web Pages 是浏览类的,用户主要是来看的:以内容展现为主,辅有少量交互.前端提供基础类库

高德客户端及引擎技术架构演进与思考

2019杭州云栖大会上,高德地图技术团队向与会者分享了包括视觉与机器智能.路线规划.场景化/精细化定位.时空数据应用.亿级流量架构演进等多个出行技术领域的热门话题.现场火爆,听众反响强烈.我们把其中的优秀演讲内容整理成文并陆续发布出来,本文为其中一篇. 阿里巴巴高级无线开发专家宋照春在高德技术专场做了题为<高德客户端及引擎技术架构演进与思考>的演讲,主要分享了高德地图客户端技术架构沿着「上漂下沉」.「模块化.Bundle化」的思路演进所做的一系列架构升级中的经验和思考. 以下为宋照春演讲内容的

一种基于Storm的可扩展即时数据处理架构思考

问题引入 使用storm可以方便的构建一种集群式的数据框架,并通过定义topo来实现业务逻辑. 但使用topo存在一个缺点, topo的处理能力来自于其启动时设置的worker数目,在很多情况下,我们需要能够根据业务压力来调整集群的处理能力,这时候单一的topo就无法解决这个问题了. 为了能够更加灵活的定义处理能力,可以考虑将原有的topo根据业务域进行拆分,做到互不干扰,灵活控制,而且为了能够更加经济的利用处理资源,可以考虑引入worker资源池的概念,达到对资源的充分利用. 但使用这种多to

即时通讯架构研究

1    系统架构 1.1 概述 即时通讯:允许两人或多人跨多样网络即时传递文字.档案.语音和视频交流的终端服务. 1.2 逻辑架构 即时通讯软件的主要功能有: 即时会话:两人或多人之间,文字.视音频的交流,包括在线消息与离线消息的发送接收,耳机.话筒音量的控制等. 组织机构:包括部门.用户.群组等级别的管理,好友列表的增删与维护,个性化名片.图标的定制与修改等. 文件目录:在线文件传输.目录共享以及离线文件存储与下载:协同浏览.播放以及远程共享等. 注册登录:注册管理,用户的登录与退出记录,消

[书目20160612]思考软件,创新设计——A段架构师的思考技术

高焕堂:在校时期主修统计学和信息管理,将近40年软件开发生涯.工作于亚洲和欧美各地区,专精于商业策略思考和系统架构设计.近年来,热衷于<it+设计>教育顾问和产品开发. 第1章  商业思维:从商业模式到架构设计 11.1  A段架构师的角色 11.2  面对复杂,唯有简单 21.3  商业环境与模式是复杂的 31.4  软件的复杂是本质性的(并非表象而已) 51.5  如何从复杂中设计出简单 71.5.1  单纯与美丽的密切联系 71.5.2  软件美何在,把酒问<对称> 71.5

中台服务架构的一点思考

中台服务架构的思想是伴随着企业规模不断扩大.业务多元化而形成的.如阿里巴巴将集团20多个核心业务中公共的.通用的业务以服务的方式沉淀到了共享业务事业部,这套共享服务体系为阿里巴巴集团的核心业务赋能,真正发挥服务重用的价值. 说到中台服务就需要提及SOA (面向服务的架构).百科上关于SOA的介绍如下: SOA是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来.接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台.操作系统和编程语言.这使得

面向服务架构的一些思考

在谈面向服务架构之前,首先来看看什么是服务.常谈的业务组件,业务方法或操作是否都是服务?真正的服务必须满足两个条件,一个服务本身是能力供给,必须有外界的需求:一个是服务本身是可复用或重用.一般来讲服务应该是可重用的任务,这种任务可以是业务方面的操作组合,也可以是一种技术能力. 面向服务的重点就是一切以服务为中心,从服务识别,服务分析,服务设计,服务开发和服务上线使用一切都是以服务为中心.但是要注意到面向服务本身不是在面向结构或面向对象基础上的一个新方法,而是对面向对象和组件化思想的提升. 面向服

关于安卓APP服务端的架构的一些思考

系统架构 1.REST 2.SOAP 技术框架 1.Servlet; 2.Spring MVC(REST); 数据格式 1.JSON 2.XML 数据库 1.MYSQL 2.MongoDB ORG框架 1.MyBatis 2.Hibernate 缓存 1.Redis 2.Memcached 通信协议 1.HTTP 2.TCP

费元星-关于百度在数据仓库-层级架构上的思考

目前在做的数据产品都是基于数据仓库上实现,主要的应用方式包括固定报表.数据查询.数据挖掘等. 在知识类相关的数据分析产品中,通常需要对多个业务系统的数据进行集成,更需要对数据分层进行科学的规划. 为什么分层 我们对数据进行分层的一个主要原因就是希望在管理数据的时候,能对数据有一个更加清晰的掌控,详细来讲,主要有下面几个原因: 清晰数据结构:每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解: 数据血缘追踪:简单来讲可以这样理解,我们最终给业务诚信的是一能直接使用的张业务表,