續(xù)一在這里:http://m.shnenglu.com/converse/archive/2009/01/14/71993.html
可能不太成熟,歡迎討論.
客戶端需要的功能: 登錄, 獲取信息(如自己的資料, 好友的在線狀態(tài),好友資料如簽名, 圖片, 其它資料等), 客戶之間發(fā)送消息
服務(wù)器端:
有以下幾種服務(wù)器:
登錄服務(wù)器:
負(fù)責(zé)管理客戶端登入/登出,驗(yàn)證登錄客戶端的合法性等,與客戶端發(fā)送心跳包維持連接的狀態(tài),在客戶端登錄之后, 告知消息服務(wù)器該用戶上線, 消息服務(wù)器查詢是否有該用戶的離線消息將消息發(fā)送給用戶.
同時(shí), 登錄服務(wù)器是僅有的C2S服務(wù)器, 也就是說所有要發(fā)送給客戶端的消息都需要經(jīng)過登錄服務(wù)器發(fā)送, 而給客戶端發(fā)送的消息都是采用udp形式發(fā)送(包括心跳包), udp容易丟失, 因此需要在發(fā)送之后對(duì)端有回應(yīng), 否則就要再試發(fā)送.
登錄服務(wù)器和下面的資料服務(wù)器,消息服務(wù)器以及其它的內(nèi)部服務(wù)器之間采用TCP長連接保持連接.
資料服務(wù)器:
負(fù)責(zé)管理客戶資料, 如圖片,個(gè)人說明,好友分組, 好友等等, 這些都需要cache, 如果在cache中查詢不到才去數(shù)據(jù)庫中查詢.
客戶端登錄之后首先往好友服務(wù)器查詢自己的資料(圖片,個(gè)人說明,好友在線狀態(tài)等), 其中查詢好友在線狀態(tài)需要和登錄服務(wù)器進(jìn)行交互.資料服務(wù)器只是一個(gè)最外部對(duì)外面開放的服務(wù)器, 底下下設(shè)各種與好友資料相關(guān)的服務(wù)器, 如圖片服務(wù)器, 個(gè)人資料服務(wù)器, 好友在線狀態(tài)服務(wù)器等.
消息服務(wù)器:
負(fù)責(zé)存取離線消息.
對(duì)外暴露的只有登錄服務(wù)器而已, 而資料服務(wù)器和消息服務(wù)器隱藏在登錄服務(wù)器之后.
大致如圖:
客戶端1 .... 客戶端n
\ | / ----> udp發(fā)送消息
登錄服務(wù)器
/ \ ----->tcp長連接
資料服務(wù)器 消息服務(wù)器
/ \ ------>tcp長連接
圖片服務(wù)器 個(gè)人資料服務(wù)器
幾個(gè)可能的性能問題:
1) 當(dāng)用戶量上來的時(shí)候服務(wù)器如何擴(kuò)容?考慮采用不同的IP地址綁定同一個(gè)域名的形式, 也就是說登錄服務(wù)器單獨(dú)一個(gè)域名, 但是擴(kuò)容之后的不同登錄服務(wù)器都綁定在這個(gè)域名上, 由客戶端的DNS域名解析自己決定與哪個(gè)登錄服務(wù)器進(jìn)行通信.
2) 服務(wù)器之間采用tcp長連接, 如果其中一個(gè)服務(wù)器宕機(jī), 如何處理?需要有好的服務(wù)器平滑切換備份機(jī)器的技術(shù), 以及好的監(jiān)控服務(wù)器機(jī)制.
3) 如何高效存取離線消息?
考慮如下一個(gè)方案:有0x00-0xff個(gè)目錄, 每個(gè)目錄有0x00-0xff個(gè)文件, 在類似bdb這樣的數(shù)據(jù)庫中存放一條記錄, key是用戶id, value是"目錄:文件", 查詢發(fā)送給某個(gè)用戶的離線消息時(shí)首先到這個(gè)數(shù)據(jù)庫中得到相應(yīng)的目錄和文件, 再取出所有給該用戶的消息(消息在這個(gè)文件中有自己的一套格式).當(dāng)用戶量上來的時(shí)候, 需要增加前面說的目錄和文件數(shù)量.
4) 如何保存用戶的在線狀態(tài)?也就是說,如何迅速做到知道哪些用戶是否在線?這個(gè)是不能用cache實(shí)現(xiàn)的, 因?yàn)閏ache存放的應(yīng)該是那些訪問頻繁同時(shí)不關(guān)注服務(wù)器停止之后是否會(huì)丟失的數(shù)據(jù), 如果用數(shù)據(jù)庫來保存, 那么數(shù)據(jù)的增刪很頻繁.
================= 分割線 ======================================
補(bǔ)充:
1)關(guān)于在線狀態(tài)服務(wù)器:單獨(dú)拿出一個(gè)服務(wù)器做這個(gè)保存在線狀態(tài)的服務(wù)器, 在內(nèi)存中保存用戶的在線狀態(tài),這臺(tái)服務(wù)器與登錄服務(wù)器相連, 有用戶登錄時(shí)發(fā)包加一條數(shù)據(jù),登出時(shí)也發(fā)包刪除一條數(shù)據(jù), 由于直接放在內(nèi)存中, 有以下的優(yōu)缺點(diǎn):優(yōu)點(diǎn)是速度快, 而且由于是一臺(tái)單獨(dú)的服務(wù)器做這個(gè)功能, 即使是千萬級(jí)別的用戶同時(shí)在線按照現(xiàn)在服務(wù)器的硬件配置也足以保存;缺點(diǎn)是假如這個(gè)服務(wù)器掛了, 數(shù)據(jù)會(huì)丟失, 但是考慮到前面的登錄服務(wù)器會(huì)每隔幾秒給客戶端發(fā)送一個(gè)心跳包查詢?cè)诰€狀態(tài),因此即使有誤差也可以控制在很短的時(shí)間里面.
因此, 現(xiàn)在的架構(gòu)變成了登錄服務(wù)器下面還隱藏著一個(gè)保存用戶在線狀態(tài)的服務(wù)器.
2) 離線消息服務(wù)器:擴(kuò)容的時(shí)候可以考慮把這部分的服務(wù)器做成分布式的, 也就是說, 暴露在最外面的是一臺(tái)服務(wù)器, 當(dāng)查詢某個(gè)用戶消息的請(qǐng)求到來時(shí), 再根據(jù)hash等方式計(jì)算出真正所在的服務(wù)器, 而這一部分服務(wù)器是分布式的, 類似于memcached那樣的.
此時(shí)架構(gòu)就變成了消息服務(wù)器下面隱藏著很多真正存放消息的服務(wù)器.
最后的架構(gòu)如下: