1、引言經(jīng)歷過(guò)稍有些規(guī)模的IM系統(tǒng)開(kāi)發(fā)的同行們都有體會(huì),要想實(shí)現(xiàn)大規(guī)模并發(fā)IM(比如億級(jí)用戶和數(shù)十億日消息量這樣的規(guī)模),在架構(gòu)設(shè)計(jì)上需要一些額外的考慮,尤其是要解決用戶高并發(fā)、服務(wù)高可用,架構(gòu)和實(shí)現(xiàn)細(xì)節(jié)上都需要不短時(shí)間的打磨。 我在過(guò)往的工作經(jīng)歷里,親手設(shè)計(jì)和實(shí)現(xiàn)了一套億級(jí)用戶量的IM,平臺(tái)上線并經(jīng)過(guò)6年多的驗(yàn)證,穩(wěn)定性和可用性被驗(yàn)證完全達(dá)到預(yù)期。 這套IM系統(tǒng),從上線至今已6年有余,本人也已經(jīng)離職創(chuàng)業(yè)近2年,但當(dāng)初設(shè)計(jì)和開(kāi)發(fā)這套系統(tǒng)時(shí)積累和收獲了大量的第一手實(shí)踐經(jīng)驗(yàn)和技術(shù)心得。 因此,想借本文把當(dāng)時(shí)的架構(gòu)設(shè)計(jì)經(jīng)歷記錄下來(lái),作為同行交流和參考,希望能提供一些啟發(fā),少走彎路。 本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào),歡迎關(guān)注。公眾號(hào)上的鏈接是: 點(diǎn)此進(jìn)入 。 2、系列文章為了更好以進(jìn)行內(nèi)容呈現(xiàn),本文拆分兩了上下兩篇。 本文是2篇文章中的第1篇:《 一套億級(jí)用戶的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等 》(本文) 《一套億級(jí)用戶的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等(稍后發(fā)布...)》 本篇主要總結(jié)和分享這套IM架構(gòu)的總體設(shè)計(jì)和服務(wù)拆分等。 3、原作者本文基于鄧昀澤的“大規(guī)模并發(fā)IM服務(wù)架構(gòu)設(shè)計(jì)”一文進(jìn)行的擴(kuò)展和修訂,感謝原作者的分享。 鄧昀澤:畢業(yè)于北京航空航天大學(xué),現(xiàn)藍(lán)貓微會(huì)創(chuàng)始人兼CEO,曾就職于美團(tuán)、YY語(yǔ)音、微軟和金山軟件等公司,有十多年研發(fā)管理經(jīng)驗(yàn)。 4、技術(shù)指標(biāo)在這套IM系統(tǒng)的架構(gòu)上,技術(shù)上我們堅(jiān)持高要求,經(jīng)過(guò)數(shù)年的驗(yàn)證,也確實(shí)達(dá)到了設(shè)計(jì)預(yù)期。 這4大技術(shù)指標(biāo)是:具體解釋就是:
5、架構(gòu)拆分從整體架構(gòu)上來(lái)說(shuō),億級(jí)用戶量的IM架構(gòu)整體上偏復(fù)雜。 傳統(tǒng)開(kāi)源的IM服務(wù)喜歡把所有服務(wù)做到1-2個(gè)服務(wù)里(Connector Service模型),這樣帶來(lái)的問(wèn)題比較嚴(yán)重。 傳統(tǒng)開(kāi)源的IM的問(wèn)題主要體現(xiàn)在:
因此,我在做架構(gòu)設(shè)計(jì)的時(shí)候盡量追求微服務(wù)化。即把整體架構(gòu)進(jìn)行分拆為子系統(tǒng),然后子系統(tǒng)內(nèi)按照業(yè)務(wù)邏輯分拆為微服務(wù)。 系統(tǒng)拆分如下圖:4個(gè)子系統(tǒng)的職責(zé)是:
其中:信令系統(tǒng)和推送系統(tǒng)是基礎(chǔ)設(shè)施,不只是可以為IM業(yè)務(wù)服務(wù),也可以承載其它類似的業(yè)務(wù)邏輯(比如客服系統(tǒng))。 在部署層面:采用存儲(chǔ)3核心機(jī)房,信令和推送節(jié)點(diǎn)按需部署的方式(國(guó)內(nèi)業(yè)務(wù)推薦8-10個(gè)點(diǎn))。實(shí)際上我們只做了了北京3個(gè)機(jī)房,上海1個(gè)機(jī)房和香港一個(gè)機(jī)房的部署,就基本上滿足了大陸 香港的業(yè)務(wù)需求。 下面將逐個(gè)介紹這4個(gè)子系統(tǒng)的細(xì)節(jié)方面。 6、IM業(yè)務(wù)系統(tǒng)一說(shuō)到IM,很多人腦海里跳出的第一個(gè)關(guān)鍵就是“即時(shí)通信”,技術(shù)上理所當(dāng)然的聯(lián)想到了socket,也就是大家成天嘴上說(shuō)的:“長(zhǎng)連接”。換句話說(shuō),很多對(duì)IM不了解或了解的不多的人,認(rèn)為IM里的所有數(shù)據(jù)交互、業(yè)務(wù)往來(lái)都是通過(guò)“長(zhǎng)連接”來(lái)實(shí)現(xiàn)的,這樣話,對(duì)于本文章中拆分出的“IM業(yè)務(wù)系統(tǒng)”就有點(diǎn)不理解了。 實(shí)際上,早期的IM(比如20年前的QQ、MSN、ICQ),確實(shí)所有數(shù)據(jù)基本都是通過(guò)“長(zhǎng)連接”(也就是程序員所說(shuō)的“socket”)實(shí)現(xiàn)。 但如今,移動(dòng)端為主端的IM時(shí)代,IM系統(tǒng)再也不是一個(gè)條“長(zhǎng)連接”走天下。 現(xiàn)在,一個(gè)典型的IM系統(tǒng)數(shù)據(jù)往來(lái)通常拆分成兩種服務(wù):
通俗一點(diǎn),也也就現(xiàn)在的IM系統(tǒng),通常都是長(zhǎng)、短連接配合一起實(shí)現(xiàn)的。 比如論壇里很多熱門技術(shù)方案都是這樣來(lái)做的,比如最典型的這兩篇:《 IM單聊和群聊中的在線狀態(tài)同步應(yīng)該用“推”還是“拉”? 》、《 IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞 》,文記里提到的“推”其實(shí)就是走的“長(zhǎng)連接”、“拉”就上指的http短連接。 對(duì)于socket長(zhǎng)連接服務(wù)就沒(méi)什么好說(shuō),就是大家最常理解的那樣。 IM業(yè)務(wù)系統(tǒng)詳細(xì)來(lái)說(shuō),就是專注處理IM相關(guān)的業(yè)務(wù)邏輯,比如:
按照微服務(wù)的原則,IM業(yè)務(wù)系統(tǒng)也被分拆為多個(gè)服務(wù),比如:
7、信令系統(tǒng)7.1 基本情況信令系統(tǒng)主要職責(zé)是3部分:1)維護(hù)用戶在線狀態(tài):因?yàn)橛脩粢?guī)模龐大,必然是多個(gè)集群,每個(gè)集群多臺(tái)服務(wù)器為用戶提供服務(wù)。 考慮到服務(wù)器運(yùn)維的復(fù)雜性,我們要假定任何一個(gè)集群,任何一個(gè)服務(wù)器都可能會(huì)掛掉,而且在這種情況下要能夠繼續(xù)為用戶提供服務(wù)。 在這種情況下,如果用戶A給用戶B發(fā)消息,我們需要知道用戶B在哪個(gè)服務(wù)器上,才能把消息正確推送給用戶B。用戶在哪個(gè)信令服務(wù),這個(gè)信息就是在線狀態(tài)數(shù)據(jù)。 2)下行消息推送:跟上一個(gè)職責(zé)有關(guān),用戶在線的時(shí)候,如果有其它用戶給他發(fā)消息,那就最好不要走離線推送,而是走在線推送。 在線推送的最后一個(gè)環(huán)節(jié),是把用戶消息推送給用戶設(shè)備,因?yàn)榫托枰烙脩舻卿浀侥膫€(gè)服務(wù)器上。 3)業(yè)務(wù)分發(fā):信令服務(wù)不只可以處理IM請(qǐng)求,也可以處理其它類型的業(yè)務(wù)請(qǐng)求。為了處理不同的業(yè)務(wù),就需要有分發(fā)能力。 具體做法是通過(guò)一個(gè)SVID(service id)來(lái)實(shí)現(xiàn),不同的業(yè)務(wù)攜帶不同的SVID,信令服務(wù)就知道如何分發(fā)了。 用戶通過(guò)登錄服務(wù)把數(shù)據(jù)(比如IM消息)發(fā)送到信令系統(tǒng),信令系統(tǒng)根據(jù)SVID轉(zhuǎn)發(fā)給IM系統(tǒng)。不管后臺(tái)有多少個(gè)業(yè)務(wù),用戶只需要一條鏈接到信令。 7.2 服務(wù)拆分信令系統(tǒng)為了實(shí)現(xiàn)以上這3個(gè)職責(zé),同時(shí)要確保我們服務(wù)可平行擴(kuò)展的能力和穩(wěn)定性,在實(shí)際的技術(shù)實(shí)現(xiàn)上,我們實(shí)際上把信令服務(wù)分拆為3個(gè)服務(wù)模塊。 如下圖所示:下面將逐個(gè)介紹這3個(gè)子服務(wù)。 7.3 Login服務(wù)Login服務(wù)主要負(fù)責(zé)維護(hù)用戶長(zhǎng)鏈接:
Login服務(wù)收到用戶登錄請(qǐng)求以后,驗(yàn)證uid/cookie,如果成功就把這個(gè)用戶的登錄信息發(fā)送給online。 此過(guò)程主要記錄的信息包含:
如果用戶發(fā)送IM消息,先發(fā)送到Login,Login轉(zhuǎn)發(fā)給Route,Route根據(jù)服務(wù)的類型(SVID),發(fā)現(xiàn)是IM協(xié)議就發(fā)送給后端的IM服務(wù)。 Login對(duì)并發(fā)要求比較高,一般要支持TCP UDP Websocket幾種方式,單服務(wù)可以做到10-250萬(wàn)之間。從服務(wù)穩(wěn)定性角度觸發(fā),建議是控制VM的CPU/內(nèi)存,單服務(wù)器以20-50萬(wàn)為合適。 Login服務(wù)器本身沒(méi)有狀態(tài),任何一個(gè)Login服務(wù)斷掉,用戶端檢測(cè)到以后重連另一個(gè)Login服務(wù)器就可以了,對(duì)整體服務(wù)可靠性基本沒(méi)有影響。 7.4 Online服務(wù)Online服務(wù)主要負(fù)責(zé)維護(hù)用戶的在線信息:
Online業(yè)務(wù)相對(duì)簡(jiǎn)單:多個(gè)Login服務(wù)器會(huì)連接到Online,定期同步用戶登錄和離線信息。 Online主要職責(zé)是:把用戶狀態(tài)信息存儲(chǔ)在Redis集群里。因此也是無(wú)狀態(tài)的,任何一個(gè)Online服務(wù)掛掉,不影響整體服務(wù)能力。 如果集群規(guī)模不大,用戶規(guī)模也不大,Online服務(wù)也可以收到Login服務(wù)里去。 如果規(guī)模比較大,建議分拆出來(lái),一方面簡(jiǎn)化Login的邏輯復(fù)雜度,同時(shí)避免寫Redis的慢操作放在Login服務(wù)里。因?yàn)長(zhǎng)ogin要同時(shí)處理50萬(wàn)以上的并發(fā)鏈接,不適合在循環(huán)里嵌入慢操作。 7.5 Route服務(wù)Route服務(wù)的設(shè)計(jì)核心,是作為信令系統(tǒng)跟其它子系統(tǒng)的交互層。Route下接Login服務(wù),可以接受用戶業(yè)務(wù)信息(IM),也可以往用戶推送下行消息。 多個(gè)后端業(yè)務(wù)系統(tǒng)可以接入到Route,按照服務(wù)類型(SVID, service id)注冊(cè)。比如IM服務(wù)可以接入到Route, 注冊(cè)SVID_IM。這樣Login接收到SVID=SVID_IM的消息,轉(zhuǎn)發(fā)給Route,Route就可以根據(jù)SVID轉(zhuǎn)發(fā)給IM相關(guān)的服務(wù)。 Route簡(jiǎn)單的根據(jù)SVID做轉(zhuǎn)發(fā),不處理具體的業(yè)務(wù)邏輯,因此也是無(wú)狀態(tài)的。一個(gè)信令集群可以有多個(gè)Route服務(wù),任何服務(wù)掛了不影響整體服務(wù)能力。 8、推送系統(tǒng)推送系統(tǒng)的核心任務(wù):是接收到給用戶發(fā)送下行消息的請(qǐng)求以后,去信令服務(wù)查詢用戶是否在線,如果在線走信令推送,如果不在線走離線推送(如 iOS的APNS 、華為推送、小米推送等)。 因?yàn)橥扑头?wù)可能出現(xiàn)大規(guī)模并發(fā)蜂擁,比如大群激烈討論的時(shí)候,會(huì)觸發(fā)億級(jí)的TPS。因此推送服務(wù)用Kafka做了削峰。 我在實(shí)際的技術(shù)實(shí)現(xiàn)上,將推送系統(tǒng)進(jìn)行了如下細(xì)分:具體就是:
這里同樣,除了Kafka以外每個(gè)服務(wù)都是無(wú)狀態(tài)的,因?yàn)橐部梢詫?shí)現(xiàn)平行擴(kuò)展和容錯(cuò),任何服務(wù)掛掉不影響整體服務(wù)可用性。 9、存儲(chǔ)系統(tǒng)存儲(chǔ)服務(wù)主要是負(fù)責(zé)消息的存儲(chǔ)和查詢,因?yàn)橄⒘烤薮?,?duì)存儲(chǔ)服務(wù)的并發(fā)能力和存儲(chǔ)量要求巨大。 為了平衡性能、空間和成本,存儲(chǔ)服務(wù)按數(shù)據(jù)的熱度進(jìn)行了分級(jí)和區(qū)別對(duì)待。 具體是:
同時(shí),為了應(yīng)對(duì)超大群的大量消息處理,存儲(chǔ)服務(wù)在實(shí)際的技術(shù)實(shí)現(xiàn)上,也做了比較細(xì)的分拆。 存儲(chǔ)服務(wù)具體拆分如下圖:具體的業(yè)務(wù)劃分就是:
消息隊(duì)列(Kafka)在這里角色比較重要,因?yàn)閷?duì)于高并發(fā)請(qǐng)求(100萬(wàn)人公眾號(hào)),需要通過(guò)消息隊(duì)列來(lái)做削峰和并行。 在具體部署上:可能是3-4個(gè)MsgProxy,后端可以對(duì)應(yīng)15個(gè)左右的MsgWriter。MsgWriter是比較慢的,需要同時(shí)操作多個(gè)數(shù)據(jù)庫(kù),還要保證操作的原子性。 10、本篇小結(jié)本篇主要總結(jié)了這套億級(jí)用戶量IM系統(tǒng)的總體架構(gòu)設(shè)計(jì),為了高性能和橫向擴(kuò)展性,基于微信的理念將整個(gè)架構(gòu)在實(shí)現(xiàn)上分成了4個(gè)子系統(tǒng),分別是:IM業(yè)務(wù)系統(tǒng)、信令系統(tǒng)、推送系統(tǒng)、存儲(chǔ)系統(tǒng)。 針對(duì)這4個(gè)子系統(tǒng),在實(shí)際的技術(shù)應(yīng)用層上,又進(jìn)行了進(jìn)一步的服務(wù)拆分和細(xì)化,使得整個(gè)架構(gòu)伸縮性大大增強(qiáng)。 end |
|