IM服務器架構實現


我把第一個問題選為: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保持長連接.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM