`

IM服务器架构实现

 
阅读更多

<转自http://www.cnblogs.com/stable/archive/2010/07/17/1779467.html>

 我把第一个问题选为:QQ的架构。呵呵,题目是不是有点大?QQ现在的最高在线用户数是1900万,我们来讨论一下要作一个这样的架构如何来作更好,大家积极发­言,这也是我这个周末为自己选择的思考题,呵呵。大家积极畅所欲言。 
  我们讨论的问题可以包括但不限于这些内容: 
  1.登录时的负载如何解决的 
  2.服务器主要作哪些事,负载如何解决 
  3.数据库负载如何解决 






按照我们的设想,对于3,是不会使用数据库来撑大访问量的,特别是一些不需要实时更新的数据,会通过一个的Server对数据进行汇总,然后在数据库比较空闲的­时间段进行批量更新。而客户端查询相关信息,也不会直接查询数据库,而是直接连接Server来获取。对于这些Server群的负载,就有很多方法了,没做过,­就不纸上谈兵啦。 


另外说说Web负载,根据HTTP协议返回的信息,QQ是使用Apache来实现Web负载的,Apache虽然定制非常方便,扩展性强,但是性能并不是最优的­。Google就实现了它自己的WebServer 
GWS 
(Gmail中是GFE??),跟它的GFS紧密结合起来,性能做到最好。 





QQ的后台用的是MySQl数据库哦,呵呵,是不是不可思议啊?不过整个MySqL都是面目全非了,被QQ的人修改的不成人形。性能非常的高,尤其数据的读取和­存储。 
QQ的服务器技术号称世界领先,呵呵, 


以前对MSN Messenger协议有所研究,MSN Messenger服务器可以分为三类:Dispatch 
Server(DS)、Notification Server(NS)、Switchboard Server(SB)。 

DS是Messenger登陆时首先连接的服务器。然后DS指定一个NS的IP返回给客户端, 
然后关闭连接。 


Messenger接着连接到得到的NS IP地址,所有的操作信息,比如添加好友、删除好 
友,更名等等都是通过NS的这个连接完成。只要Messenger在线,该连接会一直保 
持。 


如果要开始对话,发起人发送指定指令到NS,NS返回一个指定的SB IP,接受者会 
在其NS连接上也收到该SB IP的通知。然后双方均连接到该SB上进行对话,对话完 
成后关闭连接。 


以下是我对这三种服务器的看法: 


DS采用的负载均衡方式应该比较简单,通过DNS解析来做负载均衡。并且由于在DS 
上的连接都是短连接,保持时间非常短,所以应该DS服务器的数量应该不会很多。 
由于DS必须要返回一个可用的NS IP,那么内部应该还有其他种类的服务器来保存 
当前所有可用的NS服务器,以及这些NS服务器上的负载。通过DS这一层来为接下来 
的NS做负载均衡。 


NS连接均为长连接,所以在这一层上的负载由DS来调节。如果NS负载太大,新客户 
连接上DS时会返回其他相对空闲的NS服务器。当然NS服务器之间也有相互通讯的机 
制也是少不了的,比如上下线通知、对话发起等等。 


SB连接的时间介于NS和DS之间,其负载由NS来作控制。对话完成后和SB之间的连接 
就关闭了。不过由于所有的对话都在SB上进行,MS的服务器资源再强也会吃紧,所 
以现在新版的MSN Messenger都加入了P2P Message类型,在发起对话的时候会判断 
如果双方都支持P2P Message,则会直接点对点连接连接,绕过SB这一层。 



我一直在做XMPP Server 端的开发工作, 是基于Jive wildfire 
来做二次开发, 由于Jabber 是采用 TCP 
的方式来交换信息,也有用 HTTP 
的方式,那是在5222端口被封的情况下,我们会通过HTTP 
的80 断口来交换信息,基于TCP 的 Server 
有一个缺点,那就是必须要保持连接,这是很浪费资源的,当达到十万 
- 百万级的在线后,我认为最好的方式是基于UDP 的 
Server ,那也是最灵活的,做P2P 的IM Client 
也是最灵活的。 


Skype 是做P2P IM 最好的一个, 
他的方式是我最为欣赏的,不是QQ MSN 
的架构能比的,真的,这种IM 
的架够才是我们需要实现与学习的。 


象QQ这样的规模是采用分布构价的,有点象DNS服务器不是完全一样,但是可以用来理解巨大的访问量可以被复数的服务器分担。QQ的服务器也应该分DS、NS、­SB三种或其他若干,其实就是在实际应用中服务器设置的比例不同,我不知道非会员是否服务器需要记录聊天记录如果不要NS负荷也不大,在线也不用实时连接的这样­NS的负荷就大幅度下降了。而P2P是QQ用户之间交换数据于服务器无关忽略不计。而离线问题,只有在一位用户已经不在线的情况下,才向服务器发送聊天记录,或­者该用户是会员在向对方发送记录的同时在向服务器发送记录,这样服务器只需要处理会员的聊天记录和暂时无法到达的聊天记录。一台服务器用10万的并发流量来说(­理论),而且10W个用户并非同时向服务器发送记录。用户登陆由DS 
NS负责的,通知到所有的好友。这个由其他服务器负责,登陆、离线发生的频率更加稀疏。这样负载不会很大。其实不够了再加服务器。关键是构架可以扩展。对于数据­库我觉得他们是采用分布式数据库。QQ对用户没有汇总式查询。将一些用户的数据放在树的某的节点上。可以把每个节点设置成数据服务器。这样就把查询量分散了。所­有数据并不在一台服务器上,QQ应该是分布式的因为理论上不需要汇总数据,除非需要高效的汇总查询。 





很高兴能看到大家积极讨论,这两天针对于这个问题,我也有了一些自己的初步想法,拿出来与大家共享. 

前两周,听杭州研究院的同事介绍了海量数据存储方面的东西,这个讲座对我还是有点启发的.其中,在介绍有关GFS(GOOGLE自己的文件系统)的内容时,他阐­述了这样一个思想:高性能的应用系统,并不全是由高性能的硬件服务器来支持的,甚至,他们有时更多的就是一些普通的服务器,而再甚至,他们可能是目前已经不是市­场主流的废旧机器,我们就是要在这些廉价的硬件基础上,通过我们的架构设计和软件设计完成可观的高性能应用,这才是我们所应该追求的目标,也是符合绝大多数网络­公司发展现状的选择,因为网络应用系统所承载的未来用户数是不可预期的,它只会不断增大. 


如果有需要的朋友,我可以给你们发一份当时讲座用到的GFS资料.在谈到GFS的时候,我觉得对于我而言,收获最大的就是chunk server 
与 master server之间的分工,让我很受启发.简单地说,chunk server才是负责作真正逻辑的地方,而master 
server只是作了一个中介者,传递了一个信息而已,在具体的应用环境中,GFS client会向master 
server询问所要查询的数据文件在哪个chunk server上,然后GFS client就会与chunk server之间直接进行通信. 


说到QQ的架构,我想我们现在更多的是站在自己已有的知识架构上去想象和理解它,或者说,这个讨论的主题是这样更为合适些:"如果让你作QQ的网络架构,你会怎­么作?"不然,当我们在这时煞有介事地讨论QQ架构的时候,腾讯的朋友看到了,可能会觉得我们讨论的与他们实现的差别太大.所以,我想,我下面的发言内容,将会­以这个主题来进行:如果让我来作QQ的架构,我会怎么作? 


OK,现在我就把自己当作是一个QQ架构的设计者,我想象一下我会怎样在廉价的硬件服务器基础上去搭建这样的一个海量用户的网络应用系统. 


在讨论问题时,我喜欢把问题细化.我们先看一下QQ在聊天(请注意:先只谈聊天)方面具有哪些大致的功能.对于一个网络聊天程序而言,它会具有以下大致功能: 
1.账号管理(包括注册,登录验证等) 
2.好友管理(包括好友的增,删,黑名单的增,删) 
3.消息通知(用户上下线信息的转发,离线消息转发) 


总体而言,我把QQ系统的设计难点归纳为两个:一是应用服务器如何部署,二是数据库如何部署.下面,是我的设计思路. 


我的基本设计思想是:把QQ号按分段的思想进行管理(比如每100万是一个号段),每段是一个单独的QQ管理集群(暂且称为QQ server 
cluster),每个集群之间通过分布式架构支持海量用户在线.同时,会有一个全局唯一的QQ master 
server存放全局索引信息,这些信息将主要包括:号段所对应的服务器信息及状态. QQ 
cluster的主要组成,将同时包括:应用服务器(称为QQ chat server)和数据库服务器(QQ db 
server).我的可扩展架构设想是:当发现现有的用户数已经接近饱和状态时,只要增加一个相对独立的cluster,并把这个新的cluster的相关信息­注册到全局唯一的QQ 
master server上即可. 


每一个QQ server cluster应该提供哪些基本服务: 
1.对于客户端,每个cluster是一个相对独立的逻辑组,它承担了用户需要服务器支持的大多数逻辑,比如:好友上下线消息通知,离线消息转发等. 
2.同时,对于其它的cluster,要向它们提供这样的接口:好友在线状态查询,用户详细信息查询等. 
3.为了实现P2P,还要打通两个客户端之间的UDP通信通道. 
4.当客户端选择采用TCP进行通信时,还要负责消息的转发. 


那么,每一个cluster里的db都存放了哪些信息呢? 
1.存放属于本段用户的详细个人资料(包括除了必要的昵称信息等之外,还包括诸如:年龄,住址等的详细信息) 
2.存放好友名单及黑名单(而在这两个名单中,在本地的db上应该只包括必要的基本信息:好友QQ号,好友昵称等) 


当客户端登录时,客户端首先只能获得好友的简单信息,如果要想获得详细详细,就需要向本号段的cluster查询,如果cluster发现好友的号不在本号段内­,它会向其它cluster查询好友的详细信息(当然,这里的查询方法也是有多种方式的). 


说到这里,还有很重要的一点,QQ的登录又该如何来处理呢? 


1.首先,我会设置若干个(假设n个)对外开放的登录域名(比如login01.qq.com~login08.qq.com),这些域名中的每一个是可以同时­指向多个登录服务器(称为QQ 
login server)IP的,这样可以有效分担连接负载; 
2.当客户端连接到login server之后,login server将对用户进行账号认证,成功后,会向客户端发送一个cluster 
server的ip,将客户端引导到cluster上去; 
3.一旦客户端连接到cluster上成功后,所有的逻辑就由cluster来控制了. 


当然,这里仍然还有很多细节问题要考虑,比如:对于这样的分段管理,每个cluster中的QQ chat 
server可能一个还不行,那这些chat server之间就要考虑还要加一个chat 
master了.不过,这样的话,分层是不是多了一点呢?还有待更进一层的细想,等我想清楚了详细设计方案的时候,会以附件的形式配以图表发上来,此文全当一个­引子. 






> 象QQ这样的规模是采用分布构价的,有点象DNS服务器不是完全一样,但是可以用来理解巨大的访问量可以被复数的服务器分担。QQ的服务器也应该分DS、NS、­SB三种或其他若干,其实就是在实际应用中服务器设置的比例不同,我不知道非会员是否服务器需要记录聊天记录如果不要NS负荷也不大,在线也不用实时连接的这样­NS的负荷就大幅度下降了。而P2P是QQ用户之间交换数据于服务器无关忽略不计。而离线问题,只有在一位用户已经不在线的情况下,才向服务器发送聊天记录,或­者该用户是会员在向对方发送记录的同时在向服务器发送记录,这样服务器只需要处理会员的聊天记录和暂时无法到达的聊天记录。一台服务器用10万的并发流量来说(­理论),而且10W个用户并非同时向服务器发送记录。用户登陆由DS 
> NS负责的,通知到所有的好友。这个由其他服务器负责,登陆、离线发生的频率更加稀疏。这样负载不会很大。其实不够了再加服务器。关键是构架可以扩展。对于数据­库我觉得他们是采用分布式数据库。QQ对用户没有汇总式查询。将一些用户的数据放在树的某的节点上。可以把每个节点设置成数据服务器。这样就把查询量分散了。所­有数据并不在一台服务器上,QQ应该是分布式的因为理论上不需要汇总数据,除非需要高效的汇总查询。 



关于我的思路的优缺点: 

优点是: 
这样的思路类似于现实生活中电话号码的管理,它是分地区的,也就是分段的,我个人认为这样以后的扩展相对来说可能简单一点. 


缺点是: 
作为一个解决方案,这个思路并没有充分考虑到根据当前用户在线数来实现动态平衡的目标.比如说1~100万内的在线人数很少,而100万~200万号内在线的人­很多,那么这两个不同号段的服务器负载就会完全不一样,从而浪费了服务器资源. 


克服缺点的办法: 
如果要实现完全根据当前在线用户数来实现服务器负载的动态平衡,那就得将chat server与db server拨离, 让chat 
server这一层完全按动态均衡的思路来作, 
而db这一块的工作,可以抽象成一个数据管理层来作,但具体的用户数据存储仍然采用分段存储的方式,为不同的号段作不同的数据库存储. 而chat 
server这一层的思路, 基本上也是master + chunk的方式,客户端最终仍然是与chat保持长连接.

分享到:
评论

相关推荐

    小米IM通讯服务器架构图

    小米IM通讯服务器架构图

    1.4亿在线背后的故事-——-腾讯-QQ-IM后台架构的演化与启示.ppt

    腾讯 QQ IM 后台架构的演化与启示是指腾讯QQ即时通讯(IM)后台架构的演化过程和启示,从十万级到亿级在线的整个过程中,吸取了很多教训,对海量服务的理解是长期积累的结果。 演化过程可以分为三个阶段:IM 后台 ...

    陌陌IM高可用架构.pdf

    综上所述,陌陌IM的高可用架构通过合理的层设计和协议选择,实现了即时通讯系统的高可靠性、高效性和良好的可扩展性。其中,通讯协议的设计尤为关键,它直接关系到整个系统的性能和用户体验。通过这些知识点的学习,...

    Go-goim是一个golang写的IM服务器

    《Go-goim:基于Golang构建的高效IM服务器详解》 在现代互联网应用中,即时通讯(Instant Messaging,简称IM)已经成为不可或缺的一部分,无论是企业内部沟通还是社交平台,IM服务器都扮演着至关重要的角色。Go-...

    IM 即时通讯 实现实时视频通话

    首先,我们需要理解IM系统的基础架构。IM系统通常包括客户端应用、服务器端和数据中心三部分。客户端应用负责用户界面展示和交互,服务器端处理用户之间的消息传递,而数据中心则用于存储用户数据和提供大规模的消息...

    web IM 用异步实现的IM

    综上所述,"web IM 用异步实现的IM"涉及到的技术栈广泛,从前端的用户界面设计到后端的实时通信架构,都需要深入理解和熟练掌握。一个成功的Web IM系统需要兼顾功能、性能和用户体验,而异步处理是其中的关键技术之...

    带后端IM源码控制的APP聊天源码下载 52im即时通讯系统服务器打包.rar

    总之,52im即时通讯系统的源码提供了全面的聊天功能实现,对理解即时通讯系统的架构和原理有着极大的学习价值。开发者可以通过研究和实践,不仅可以掌握即时通讯系统的开发,还能提升自身在服务器端编程、网络通信、...

    cdeer-im, 基于Netty+Redis+protobuf开发的即时通讯服务器.zip

    **即时通讯服务器基础** 即时通讯(Instant Messaging,简称IM)服务器是用于实现实时通信的应用程序,它...开发者可以通过学习和研究这个项目,深入了解IM服务器的架构设计和关键技术应用,进一步提升自己的技能。

    im:分布式即时消息服务器架构

    分布式即时消息服务器架构是现代互联网应用中不可或缺的一部分,它能够处理海量用户之间的实时通信需求,如聊天、通知推送等。在这种架构中,Go语言因其高效、简洁和并发能力强等特点,常被选作开发语言。本文将深入...

    腾讯IM架构

    ### 腾讯IM架构演进关键知识点 #### 一、背景与挑战 - **初期架构**:腾讯的即时通讯(IM)系统最初采用的是较为简单的架构设计,适用于较小规模的在线用户数量(如十万级别)。然而,随着用户基数的增长,这种架构...

    一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等.docx

    - **高可用性**:即使部分机房或服务器故障,服务仍能正常运行,通过分布式和冗余备份实现。 - **实时性**:在线用户的消息能在1秒内送达,实际达到75%的消息在120毫秒内传递。 - **有序性**:保证消息的发送和接收...

    极光IM全功能

    5. **推送服务**:极光IM集成了高效的推送服务,即使在应用后台或关闭状态下,也能收到新消息通知。 6. **群组管理**:提供创建、解散、加入、踢人等群组管理功能,支持大规模群聊,适应不同的社交场景。 7. **...

    Go-imgo是一个基于goim开发的推送服务器和IM服务器

    2. **IM服务**:实现即时通讯功能,允许用户进行一对一、一对多、群组聊天,支持文本、图片、语音等多种消息类型。 3. **高可用**:通过负载均衡、故障转移等手段确保服务的稳定性和可靠性。 4. **可扩展性**:设计...

    IM即时通信,包含web端实现

    我们将从系统架构、主要技术选型、核心功能实现以及优化策略等方面进行详尽阐述。 一、系统架构 这款IM即时通信系统采用微服务架构,基于NutzBoot框架构建。NutzBoot是Nutz团队推出的企业级Java开发框架,它简化了...

    风车IM即时通讯聊天系统源码-聊天APP-附APP-带安装教程

    3. **服务器架构**:作为独立部署的系统,风车IM的服务器架构可能包括前端和后端两部分。前端负责用户界面和交互,而后端处理逻辑和数据存储。文件名中的“前端(上传到wwwroot)”表明这部分代码用于Web服务器的根...

    c# IM从客户端程序登录服务器程序示例

    在本文中,我们将深入探讨如何使用C#编程语言创建一个即时消息(IM)客户端程序,以便连接到服务器并实现登录功能。C#是一种强大的、面向对象的编程语言,非常适合开发网络应用程序,包括IM系统。 首先,我们需要...

    Android 基于XMPP协议IM聊天实现(客户端+服务端) 源码

    在本文中,我们将深入探讨如何使用XMPP协议在Android平台上实现一个完整的即时通讯(IM)系统,包括客户端和服务器端的实现。XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的开放标准,广泛用于...

Global site tag (gtag.js) - Google Analytics