“id串行化”到底是怎么實現(xiàn)的?

2018-09-06 17:59 更新

一、需求緣起

在上一篇文章《消息“時序”與“一致性”為何這么難?》中,介紹了一種為了保證“所有群友展示的群消息時序都是一致的”所使用的“id串行化”的方法:讓同一個群gid的所有消息落在同一臺服務(wù)器上處理。

有朋友就要問了,如何保證一個群gid的消息落到同一個服務(wù)器處理呢,“id串行化”具體是怎么實現(xiàn)的呢,這個問題在年初的一篇文章中描述過,這里再給有疑問的同學(xué)解答一下。


二、互聯(lián)網(wǎng)高可用常見分層架構(gòu)


客戶端,反向代理層,接入層(此圖是http短鏈接接入,群聊消息的話是tcp長連接接入),服務(wù)層(處理群消息業(yè)務(wù)邏輯),存儲層(緩存cache存儲,固化db存儲),這是互聯(lián)網(wǎng)常見的高可用分層架構(gòu)。

服務(wù)層的引入至關(guān)重要,群消息的投遞不能保證落在同一個接入層,但可以保證落在同一個服務(wù)層。


三、服務(wù)層上下游細(xì)節(jié)

服務(wù)化的service一般由RPC-server框架實現(xiàn),上游應(yīng)用是多線程程序(站點層http接入應(yīng)用,或者長連接tcp接入應(yīng)用)一般通過RPC-client訪問service,而RPC-client內(nèi)部又通過連接池connection-pool訪問下游的service(為了保證高可用,是一個service集群)。

任務(wù)隊列

如上圖:

(1)上游是業(yè)務(wù)應(yīng)用(站點層http接入應(yīng)用,或者長連接tcp接入應(yīng)用)

(2)下游是service集群

(3)業(yè)務(wù)應(yīng)用,它又分為了這么幾個部分

(3.1)最上層是任務(wù)隊列【或許web-server例如tomcat幫你干了這個事情了】

(3.2)中間是工作線程【或許web-server的工作線程或者cgi工作線程幫你干了線程分派這個事情了】,每個工作線程完成實際的業(yè)務(wù)任務(wù),典型的工作任務(wù)是通過服務(wù)連接池進行RPC調(diào)用

(3.3)最下層是服務(wù)連接池,所有的RPC調(diào)用都是通過服務(wù)連接池往下游服務(wù)去發(fā)包執(zhí)行的


工作線程的典型工作流偽代碼是這樣的:
void work_thread_routine(){
Task t = TaskQueue.pop(); // 獲取任務(wù)
// 任務(wù)邏輯處理,組成一個網(wǎng)絡(luò)包packet,調(diào)用下游RPC接口
ServiceConnection c = CPool.GetServiceConnection(); 
// 從Service連接池獲取一個Service連接
c.Send(packet); // 通過Service連接發(fā)送報文執(zhí)行RPC請求
CPool.PutServiceConnection(c); // 將Service連接放回Service連接池
}

如何保證同一個群gid的消息落在同一個service上呢?

只要對服務(wù)連接池進行少量改動:

獲取Service連接的CPool.GetServiceConnection()【返回任何一個可用Service連接】改為

CPool.GetServiceConnection(long id)【返回id取模相關(guān)聯(lián)的Service連接】


只要傳入群gid,就能夠保證同一個群的請求獲取到同一個連接,從而使請求落到同一個服務(wù)Service上。

需要注意的是,連接池不關(guān)心傳入的long id是什么業(yè)務(wù)含義

(1)傳入群gid,同gid的請求落在同一個service上

(2)傳入用戶uid,同uid的請求落在同一個service上

(3)傳入任何業(yè)務(wù)xid,同業(yè)務(wù)xid的請求落在同一個service上


四、其他問題

提問:id串行化訪問service,同一個id訪問同一個service,當(dāng)service掛掉時,是否會影響service的可用性?

答:不會,當(dāng)有下游service掛掉的時候,service連接池能夠檢測到連接的可用性,取模時要把不可用的服務(wù)連接排除掉。


提問:取模訪問service,是否會影響各連接上請求的負(fù)載均衡?

答:不會,只要數(shù)據(jù)訪問id是均衡的,從全局來看,由id取模獲取各連接的概率也是均等的,即負(fù)載是均衡的。


五、總結(jié)

升級RPC-client內(nèi)部的連接池,在service連接選取上做微小改動,就能夠?qū)崿F(xiàn)“id串行化”,實現(xiàn)不同類型的業(yè)務(wù)gid/uid等的串行化、序列號需求(這下查找日志就方便了,一個群gid/用戶uid的日志只需去一臺機器grep啦)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號