汽車之家App詳細(xì)介紹、汽車之家app下載安裝
1.前言
早期之家在C端產(chǎn)品的即時(shí)通信功能是直接使用第三方商業(yè)軟件服務(wù)(SaaS),功能擴(kuò)展性上存在很大制約,某些定制化業(yè)務(wù)需求很難實(shí)現(xiàn),考慮到后續(xù)業(yè)務(wù)發(fā)展需要、數(shù)據(jù)安全、內(nèi)容實(shí)時(shí)審核及性能、自主可控高可用架構(gòu)等因素,決定自主開發(fā)IM即時(shí)通信平臺(tái)并逐步迭代替換。
2.網(wǎng)絡(luò)通信框架及協(xié)議
2.1
網(wǎng)絡(luò)通信框架
網(wǎng)絡(luò)通信系統(tǒng)通常可以選擇原生NIO庫或者第三方網(wǎng)絡(luò)框架進(jìn)行開發(fā),原生NIO的類庫API比較底層基礎(chǔ),缺少對(duì)常用操作的封裝,例如粘包、解碼、重連等,開發(fā)工作量和維護(hù)成本會(huì)比較高,需要關(guān)注很多底層的東西。我們選擇了目前非常熱門的網(wǎng)絡(luò)框架Netty進(jìn)行開發(fā),Netty功能強(qiáng)大開發(fā)門檻較低,預(yù)置了多種主流協(xié)議編解碼功能,成熟、穩(wěn)定,且修復(fù)了大量已經(jīng)發(fā)現(xiàn)的JDK NIO BUG。
? Netty具備如下優(yōu)點(diǎn):
1.入門簡(jiǎn)單,文檔齊全,無其他依賴,只依賴 JDK 就夠了;
2.使用簡(jiǎn)單,預(yù)置了多種編解碼功能,支持多種主流協(xié)議,對(duì)大量常用操作進(jìn)行了封裝,減少開發(fā)周期;
3.高性能,高吞吐,低延遲,資源消耗少;
4.靈活的線程模型,支持阻塞和非阻塞的I/O 模型;
5.代碼質(zhì)量高,目前主流版本基本沒有 Bug;
6.社區(qū)活躍,版本迭代周期短,發(fā)現(xiàn)的BUG可以被及時(shí)修復(fù),同時(shí),更多的新功能會(huì)加入;
7.經(jīng)歷了大規(guī)模的商業(yè)應(yīng)用考驗(yàn),穩(wěn)定性得到驗(yàn)證。
2.2
通信協(xié)議
TCP是個(gè)“流”協(xié)議,就是沒有界限的一串?dāng)?shù)據(jù),數(shù)據(jù)傳輸時(shí)可能會(huì)存多包或半包傳輸?shù)那闆r,原因如下:
1. 應(yīng)用程序?qū)懭胱止?jié)大小于套接口發(fā)送緩沖區(qū)大小;
2. 進(jìn)行 MSS 大小的 TCP 分段;
3. 以太網(wǎng)幀的 payload 大于 MTU 進(jìn)行 IP 分片
? 解決策略
1. 消息定長,例如每個(gè)報(bào)文大小固定200字節(jié),如果不夠,空位補(bǔ)空格。
2. 用回車符進(jìn)行分割,例如FTP協(xié)議。
3. 約定特殊字符作為消息結(jié)束標(biāo)記。
4. 將消息分為消息頭和消息體,消息頭中包含表示消息總長度(或消息體長度)
5. 更復(fù)雜的應(yīng)用層協(xié)議。
按約定的方式編解碼保證數(shù)據(jù)完整性,就是通信協(xié)議。將消息分為消息頭和消息體是最常見的協(xié)議設(shè)計(jì)方式(定長消息頭,可變長度消息體),如下圖:
? 消息頭
固定長度字節(jié)來標(biāo)記消息類型,及消息體字節(jié)長度。
?消息體
可以使用文本、XML、JSON、Protobuf等擴(kuò)展性好的數(shù)據(jù)格式,盡量考慮以下幾點(diǎn):
1. 精簡(jiǎn)消息體大小,不要有冗余數(shù)據(jù),減少網(wǎng)絡(luò)帶寬占用(尤其是大量用戶發(fā)消息群聊場(chǎng)景下),提高傳輸效率
2. 數(shù)據(jù)安全性(例如加密傳輸)
3. 編碼效率及可擴(kuò)展性
? 除了自己設(shè)計(jì)實(shí)現(xiàn)通信協(xié)議,還可以直接使用現(xiàn)成的設(shè)計(jì)好的公開協(xié)議,如目前比較流行的websocket協(xié)議,相對(duì)于私有協(xié)議有以下優(yōu)點(diǎn):
1. 瀏覽器直接支持,方便web端接入
2. 降低接入成本,websocket是公開協(xié)議,接入時(shí)不需要在協(xié)議規(guī)范上耗費(fèi)太多的溝通時(shí)間。
3. 很多框架包括Netty都自帶實(shí)現(xiàn)了websocket協(xié)議解碼器。
3.架構(gòu)設(shè)計(jì)
客戶端:用戶收發(fā)消息終端
接入層:為客戶端連接、收發(fā)消息、關(guān)系建立提供入口
數(shù)據(jù)層:負(fù)責(zé)各類業(yè)務(wù)邏輯數(shù)據(jù)及消息數(shù)據(jù)緩存或持久化存儲(chǔ),及消息指令的分發(fā)渠道。
3.1
消息設(shè)置
聊天場(chǎng)景常見的消息類型通常有:文本、圖片、表情、語音,視頻。我們把消息分為消息類型,及消息內(nèi)容兩部分,客戶端通過識(shí)別消息類型去解析消息內(nèi)容并展示,像圖片視頻等消息,并不需要通過消息即時(shí)傳遞其內(nèi)容,而是先將圖片或視頻上傳到文件服務(wù)器,消息中只需要把uri帶過去,并且?guī)蟗ase64編碼的縮略圖即可,如下示例:
msgType:msg_image
msgContent: { user: { id:1,name:xxx,portrait:xxxx }, content: "縮略小圖base64編碼",url:"大圖地址", extra: "" }
消息下發(fā)流程如下圖:
如圖,整體思路是將上行消息通過webapi寫入消息隊(duì)列,socket服務(wù)器通過消息隊(duì)列或離線消息庫進(jìn)行增量消息分發(fā)同步。
socket服務(wù)承載連接著所有在線用戶,發(fā)生部署上線將會(huì)導(dǎo)致所有在線用戶斷開重連,瞬間大量增加其它服務(wù)器的連接壓力,且對(duì)部分用戶行為可能會(huì)有短暫的影響,上行消息通過webAPI實(shí)現(xiàn),統(tǒng)一了消息入口,方便各類渠道消息的接入,并且使得socket服務(wù)的職責(zé)變得簡(jiǎn)單單一,僅用于保持連接和推送消息,上行消息業(yè)務(wù)邏輯頻繁變動(dòng)時(shí)僅需要重新部署webAPI,對(duì)用戶基本無感知。
還有一些建議是,對(duì)消息進(jìn)行合并,壓縮能極大提升消息推送吞吐能力,減少帶寬占用,經(jīng)測(cè)試十條以上消息壓縮率能達(dá)到80%左右;細(xì)分消息隊(duì)列,按不同維度拆分消息隊(duì)列可以分散壓力防止某類消息高峰期對(duì)其它業(yè)務(wù)消息造成延遲推送,保證其它消息的時(shí)效性,比如可以按場(chǎng)景用戶消息,系統(tǒng)指令等各自使用獨(dú)立的消息隊(duì)列。
3.2
消息擴(kuò)散
消息擴(kuò)散分發(fā)是im設(shè)計(jì)的重點(diǎn),尤其是一對(duì)多的場(chǎng)景,如群聊。簡(jiǎn)單的說就是每條消息需要擴(kuò)散給群里所有人收到,通常有兩種方式,讀擴(kuò)散,寫擴(kuò)散。什么是讀擴(kuò)散?什么是寫擴(kuò)散?
? 讀擴(kuò)散:
描述:每條消息只存一份,群組所有成員讀取這一份數(shù)據(jù)。
優(yōu)點(diǎn):節(jié)省存儲(chǔ)空間,無寫入壓力。
缺點(diǎn):
1. 獲取離線增量消息邏輯復(fù)雜,需要根據(jù)用戶所有會(huì)話關(guān)系去遍歷獲取,且并未知道會(huì)話是否有增量消息,會(huì)造成大量無效空讀,效率極慢。
2. 針對(duì)消息做單個(gè)用戶個(gè)性化操作時(shí)設(shè)計(jì)會(huì)變的麻煩,比如其中一個(gè)用戶刪除消息,已讀回執(zhí)等操作時(shí),不能去影響其它用戶的視角。
? 寫擴(kuò)散:
描述:每個(gè)用戶有獨(dú)立的消息列表,每條消息給所有消息關(guān)聯(lián)人同步一份副本。
優(yōu)點(diǎn):讀取邏輯簡(jiǎn)單,效率極快,通過用戶自身消息列表一次性獲取所有離線增量消息即可,用戶個(gè)性化操作實(shí)現(xiàn)簡(jiǎn)單,不會(huì)影響其它用戶的視角。
缺點(diǎn):存儲(chǔ)空間增加,寫入壓力較大。
兩種方案如圖所示:
對(duì)比兩種消息擴(kuò)散方案優(yōu)缺點(diǎn)都比較明確,同時(shí)也都面臨無法接受的極端情況,比如讀擴(kuò)散,如果某用戶擁有巨量會(huì)話,那他每次上線時(shí)讀取消息就是災(zāi)難,再如寫擴(kuò)散,如遇到萬人群,每條消息都會(huì)產(chǎn)生一萬分副本,作為設(shè)計(jì)者必須根據(jù)實(shí)際情況從邏輯上去結(jié)合兩種方案來平衡讀寫壓力。
消息寫擴(kuò)散按需延遲擴(kuò)散,我們通過登陸時(shí)間把用戶分類活躍和非活躍,只對(duì)活躍用戶進(jìn)行即時(shí)寫擴(kuò)散,非活躍用戶在上線時(shí)做一次補(bǔ)償同步操作,這樣能有效分散消息寫入壓力,還能對(duì)減少僵尸賬號(hào)進(jìn)行無意義消息副本同步。
3.3
IMSDK架構(gòu)構(gòu)圖
IMSDK架構(gòu)按模塊分工可以分為中間件層、核心層、協(xié)議層。
?中間件層
負(fù)責(zé)請(qǐng)求連接時(shí)需要的Token,以及對(duì)Token的緩存、Token過期更新等邏輯。當(dāng)App啟動(dòng)之后平臺(tái)層會(huì)設(shè)置用戶信息到中間件,中間件根據(jù)設(shè)置的用戶信息判斷本地是否緩存該用戶的Token,如果有則直接用該Token進(jìn)行連接;如果沒有則會(huì)請(qǐng)求接口獲取Token。獲取到之后使用獲取到的Token進(jìn)行連接,連接成功之后將該Token本地緩存,方便下次使用。如果連接過程中服務(wù)器端返回Token過期的錯(cuò)誤,客戶端會(huì)刪除掉本地緩存的Token,并重新請(qǐng)求Token進(jìn)行再次連接。
?核心層
包含連接模塊、監(jiān)聽模塊、API封裝模塊、日志模塊、本地?cái)?shù)據(jù)庫模塊。連接模塊負(fù)責(zé)Socket的連接、保活、斷線重連、斷開、收發(fā)消息等操作,連接模塊每隔50秒發(fā)送一次ping來保活,連接模塊重連機(jī)制是2秒、4秒、8秒、16秒等2的n次方逐漸增加,當(dāng)重試次數(shù)到10次后會(huì)認(rèn)為當(dāng)前網(wǎng)絡(luò)有問題,不再重試,等待監(jiān)聽網(wǎng)絡(luò)變化或者前后臺(tái)切換之后再次重試;監(jiān)聽模塊當(dāng)收到會(huì)話變更、消息變更、連接狀態(tài)變更時(shí)將變更內(nèi)容通知到所有注冊(cè)監(jiān)聽的業(yè)務(wù)層,業(yè)務(wù)層根據(jù)收到的通知做出相應(yīng)處理。
API封裝模塊提供一些SDK基礎(chǔ)功能的API到業(yè)務(wù)層,例如發(fā)送消息、撤回消息、刪除消息、獲取會(huì)話未讀數(shù)、會(huì)話草稿等等,業(yè)務(wù)層調(diào)用提供的API完成相關(guān)功能。日志模塊提供日志采集的API,將每一條日志順序的記錄到日志文件中。日志模塊還負(fù)責(zé)日志文件的創(chuàng)建、刪除、保存與上傳工作。本地?cái)?shù)據(jù)庫模塊負(fù)責(zé)數(shù)據(jù)庫相關(guān)的工作,當(dāng)上層設(shè)置用戶信息時(shí),數(shù)據(jù)庫模塊會(huì)打開相應(yīng)的數(shù)據(jù)庫,如果沒有則會(huì)新建。數(shù)據(jù)庫模塊負(fù)責(zé)會(huì)話表和消息表的創(chuàng)建,負(fù)責(zé)會(huì)話和消息的增、刪、改、查。數(shù)據(jù)庫模塊執(zhí)行操作時(shí)會(huì)增加一些必要的邏輯到其中,例如,在插入消息時(shí)需要更新會(huì)話的未讀數(shù)、會(huì)話的最后一條消息;在刪除消息時(shí)需要更新會(huì)話的未讀數(shù)、會(huì)話的最后一條消息;在消息已讀功能中需要修改會(huì)話的未讀數(shù)等等。
?協(xié)議層
主要負(fù)責(zé)跟服務(wù)端通訊內(nèi)容的編解碼工作,包括消息的編解碼、會(huì)話的編解碼、命令的編解碼等工作,協(xié)議層將收到的數(shù)據(jù)進(jìn)行解析,區(qū)分出諸如收到新消息、刪除消息、撤回消息、增加會(huì)話、刪除會(huì)話、會(huì)話更新等行為,同時(shí)將收到的數(shù)據(jù)解碼成消息或者會(huì)話Model傳遞到上層,通知到業(yè)務(wù)層。
3.4
連接流程圖
App需要同App Server進(jìn)行數(shù)據(jù)交互,獲取IM連接需要的Token數(shù)據(jù),并且App Server負(fù)責(zé)維護(hù)業(yè)務(wù)數(shù)據(jù),如用戶數(shù)據(jù)、會(huì)話數(shù)據(jù)、好友關(guān)系等;
App通過Token數(shù)據(jù)與IM Server進(jìn)行連接,建立數(shù)據(jù)通道實(shí)現(xiàn)消息的實(shí)時(shí)接收與推送功能;
IM Server維護(hù)App的連接狀態(tài),在接收實(shí)時(shí)消息時(shí)判斷用戶是否在線,將消息轉(zhuǎn)發(fā)給目標(biāo)設(shè)備或保存為離線消息;
?會(huì)話及氣泡:
在面對(duì)特殊用戶會(huì)話較多時(shí)每次從服務(wù)拉取會(huì)話信息時(shí)將面臨較大壓力,我們采用本地和服務(wù)端結(jié)合方案實(shí)現(xiàn),本地緩存一份會(huì)話,接收消息對(duì)會(huì)話氣泡進(jìn)行疊加,本地會(huì)話設(shè)置發(fā)生變更如免打擾,隱藏會(huì)話,已讀消息等,上報(bào)給服務(wù)端,服務(wù)端在發(fā)生好友關(guān)系或加入群組等操作時(shí)產(chǎn)生會(huì)話,或會(huì)話信息變更時(shí)也會(huì)對(duì)本地進(jìn)行同步,服務(wù)器和本地之間會(huì)話同步包括連接時(shí)同步、實(shí)時(shí)同步、主動(dòng)同步。
連接時(shí)同步:用戶每次連接時(shí)會(huì)向服務(wù)器傳遞會(huì)話唯一標(biāo)識(shí),服務(wù)端通過用戶傳遞的標(biāo)識(shí)進(jìn)行邏輯判斷并向用戶推送會(huì)話數(shù)據(jù),包括全部會(huì)話和增量會(huì)話,SDK接收到會(huì)話數(shù)據(jù)后進(jìn)行本地的新增、修改、刪除操作,并通知給UI層,本地會(huì)話“標(biāo)識(shí)”由服務(wù)端每次同步會(huì)話時(shí)提供。
實(shí)時(shí)同步:本地會(huì)話修改會(huì)通知給服務(wù)端,服務(wù)端接收到會(huì)話信息變更時(shí),會(huì)即時(shí)通過IM推送給SDK,其中包括新增、修改、刪除會(huì)話的操作,SDK接收到會(huì)話數(shù)據(jù)后進(jìn)行本地的新增、修改、刪除操作,并通知給UI層。
主動(dòng)同步:客戶端接收到不存在的會(huì)話消息時(shí),會(huì)主動(dòng)向服務(wù)器獲取此會(huì)話信息進(jìn)行本地保存并通知UI層。
會(huì)話設(shè)計(jì)圖:
會(huì)話部分字段:
單聊:兩個(gè)用戶之間進(jìn)行一對(duì)一的聊天,聊天消息可以持久化保存至本地進(jìn)行查看。
群組:兩個(gè)或兩個(gè)以上的用戶在同一個(gè)會(huì)話中進(jìn)行聊天,發(fā)送的消息會(huì)被群組所有成員接收并可以持久化保存至本地進(jìn)行查看。
公眾號(hào):企業(yè)或官方通過系統(tǒng)賬號(hào)向單個(gè)或多個(gè)賬號(hào)推送消息,消息可以持久化保存至本地進(jìn)行查看。
聊天室:一個(gè)或多個(gè)用戶在同一個(gè)會(huì)話中進(jìn)行聊天,發(fā)送的消息會(huì)被推送至當(dāng)前聊天室中所有用戶,用戶接收端消息不會(huì)保存本地。
本地記錄每次會(huì)話同步時(shí)間,連接時(shí)服務(wù)端根據(jù)本地上報(bào)最后更新時(shí)間對(duì)比,增量同步變動(dòng)過的會(huì)話記錄,保證本地會(huì)話與服務(wù)器端保持一致。之家的會(huì)話列表體現(xiàn)在個(gè)人主頁的消息部分,如下:
4.服務(wù)器優(yōu)化
我們系統(tǒng)的設(shè)計(jì)要求是單機(jī)百萬連接支持、下行消息QPS一百萬。由于一個(gè)連接會(huì)占用一個(gè)文件描述符,首先就要對(duì)系統(tǒng)的文件描述符上限做調(diào)整,讓服務(wù)器能夠支持百萬級(jí)連接的建立;
# /etc/security/limits.conf
* soft nporc 1500000
* hard nporc 1500000
* soft nofile 1500000
* hard nofile 1500000
# /etc/sysctl.conf
fs.nr_open = 3000000
fs.file-max = 3000000
我們使用Nginx作為七層負(fù)載,并且開啟了TLS保障數(shù)據(jù)的傳輸安全。當(dāng)Nginx層作為客戶端在與后端應(yīng)用服務(wù)器建立連接的時(shí)候,會(huì)遇到本地端口瓶頸,可以依據(jù)TCP四元組規(guī)則,增加后端應(yīng)用服務(wù)器的監(jiān)聽端口,來實(shí)現(xiàn)本地端口的復(fù)用,從而突破本地端口資源的限制;
在實(shí)際壓測(cè)過車中,客戶端接收消息的毛刺問題比較嚴(yán)重,經(jīng)排查發(fā)現(xiàn)nginx服務(wù)器有丟包,并且CPU的使用非常不均衡,特別是軟中斷,只集中在少數(shù)CPU上。為解決以上問題前,先了解下網(wǎng)卡收包流程以及相關(guān)的一些概念。
網(wǎng)卡收到數(shù)據(jù)幀后,將數(shù)據(jù)幀以DMA的方式拷貝到內(nèi)存的Ring Buffer中,該步驟不需要CPU的參與。當(dāng)拷貝完成后,網(wǎng)卡便會(huì)觸發(fā)一個(gè)網(wǎng)卡硬件中斷,CPU必須立即響應(yīng)硬件中斷,CPU根據(jù)中斷類型,在中斷注冊(cè)表中查找對(duì)應(yīng)的中斷處理程序,然后調(diào)用網(wǎng)卡注冊(cè)的中斷處理程序(網(wǎng)卡驅(qū)動(dòng)),此后網(wǎng)卡驅(qū)動(dòng)程序觸發(fā)一個(gè)軟中斷,自此硬件中斷返回,硬中斷不會(huì)做過多事情,它只負(fù)責(zé)通知驅(qū)動(dòng)有數(shù)據(jù)到達(dá),具體的操作由軟中斷過程來處理。
DMA是Direct Memory Access,直接存儲(chǔ)器訪問。在DMA出現(xiàn)之前,CPU與外設(shè)之間的數(shù)據(jù)傳送方式有程序傳送方式、中斷傳送方式。CPU是通過系統(tǒng)總線與其他部件連接并進(jìn)行數(shù)據(jù)傳輸,DMA就是指外部設(shè)備不通過CPU而直接與系統(tǒng)內(nèi)存交換數(shù)據(jù)的接口技術(shù)。
Ring Buffer網(wǎng)卡環(huán)形緩沖區(qū),如果該緩沖區(qū)被占滿,新到來的數(shù)據(jù)包將會(huì)被丟棄,從而導(dǎo)致丟包。把該緩沖區(qū)由原來的512調(diào)整到2048后,丟包問題得以解決,方法如下:
查看當(dāng)前Buffer
ethtool -g em1
Ring parameters for em1:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
ethtool -G em1 rx 2048
ethtool -G em1 tx 2048
修改
ethtool -G em1 rx 4096
ethtool -G em1 tx 4096
4.1
設(shè)置網(wǎng)卡隊(duì)列
對(duì)于CPU軟中斷不均衡,與網(wǎng)卡的設(shè)置與CPU的親和力綁定有直接關(guān)系,借用網(wǎng)絡(luò)一張圖先了解下RSS多隊(duì)列網(wǎng)卡,如下:
當(dāng)網(wǎng)卡收到報(bào)文時(shí),通過Hash包頭的SIP、SPort、DIP、DPort四元組信息,將數(shù)據(jù)投遞到相應(yīng)的網(wǎng)卡隊(duì)列,同時(shí)會(huì)觸發(fā)該隊(duì)列綁定的中斷,通知CPU進(jìn)一步處理;由此可知CPU使用不均衡,無非就是兩個(gè)原因,隊(duì)列收到的數(shù)據(jù)包不均衡或者CPU與網(wǎng)卡隊(duì)列綁定不合理導(dǎo)致;
# 設(shè)定網(wǎng)卡隊(duì)列
ethtool -L em1 combined 16
4.2
網(wǎng)卡中斷號(hào)
Interrupt Request,簡(jiǎn)稱IRQ,中斷就是由硬件或軟件所發(fā)送的中斷請(qǐng)求信號(hào)。系統(tǒng)上的每個(gè)硬件設(shè)備都會(huì)被分配一個(gè) IRQ 號(hào),通過這個(gè)唯一的 IRQ 號(hào)就能區(qū)是來自哪個(gè)硬件了。開啟了多隊(duì)列的網(wǎng)卡,每個(gè)隊(duì)列都會(huì)有唯一的中斷號(hào)。
# 查看網(wǎng)卡隊(duì)列中斷號(hào)
cat /proc/interrupts |grep em1 |awk '{print $1 $NF}'
4.3
CPU親和力綁定
把每個(gè)網(wǎng)卡隊(duì)列與CPU一一綁定,均衡CPU的使用
# CPU綁定
echo /proc/irq/107/smp_affinity_list 0
echo /proc/irq/108/smp_affinity_list 1
中斷號(hào)為107的隊(duì)列綁定0號(hào)CPU,中斷號(hào)為108的隊(duì)列綁定1號(hào)CPU,依此類推,每個(gè)網(wǎng)卡隊(duì)列都需要綁定到不同的CPU核上,這樣我們就完成了網(wǎng)卡隊(duì)列的設(shè)置以及與CPU的綁定。
這里還有個(gè)問題是,CPU不緊要處理網(wǎng)路數(shù)據(jù),還要處理Nginx應(yīng)用,這個(gè)時(shí)候CPU資源的分配要根據(jù)具體的壓測(cè)情況進(jìn)行調(diào)整;
4.4
Intel Flow Director
上面提到投遞到網(wǎng)卡隊(duì)列的數(shù)據(jù)包是均衡的,如何能做到均衡呢?有個(gè)辦法是使用Intel以太網(wǎng)FD( Flow Director)技術(shù),自定義數(shù)據(jù)包投遞規(guī)則,應(yīng)用監(jiān)聽多個(gè)端口,不同目標(biāo)端口的數(shù)據(jù)包按制定的規(guī)則投遞到相應(yīng)的網(wǎng)卡隊(duì)列,從而達(dá)到均衡數(shù)據(jù)包的目的,進(jìn)而均衡CPU的使用;
# 數(shù)據(jù)投遞規(guī)則 根據(jù)目的端口把數(shù)據(jù)投遞到不同隊(duì)列
ethtool --features em1 ntuple on
ethtool --config-ntuple em1 flow-type tcp4 dst-port 9500 action 0 loc 1
ethtool --config-ntuple em1 flow-type tcp4 dst-port 9501 action 1 loc 2
至此網(wǎng)卡丟包以及CPU使用率不均衡的問題得到解決,基本就是解決了客戶端接收數(shù)據(jù)毛刺的問題;
4.5
其他優(yōu)化
對(duì)部分需要更高時(shí)時(shí)性及穩(wěn)定的用戶,如客服、商家號(hào)等,可以增加專用服務(wù)器來應(yīng)對(duì),專用服務(wù)器通常接入量較小,連接和消息推送都會(huì)更穩(wěn)定快速。
增加備用域名(不同cdn),在連接失敗重試過程中使用可有效減少外部網(wǎng)絡(luò)波動(dòng)帶來的影響,使系統(tǒng)更加穩(wěn)定可靠。我們之前有一次線上故障,使用的第三方的即時(shí)通訊服務(wù),
當(dāng)時(shí)該服務(wù)商的一個(gè)關(guān)鍵域名被誤封,導(dǎo)致整個(gè)即時(shí)通訊服務(wù)不可用,由于處理過程復(fù)雜,故障持續(xù)了半天的時(shí)間才得以恢復(fù)。基于此,我們自研的時(shí)候,把這部分設(shè)計(jì)了進(jìn)去。
為提高連接效率及服務(wù)器連接壓力SDK增加了token緩存機(jī)制,IM連接成功后,會(huì)將token進(jìn)行本地緩存,當(dāng)設(shè)備再次觸發(fā)連接時(shí),會(huì)優(yōu)先檢查本地是否存在token,如存在立刻使用緩存數(shù)據(jù)進(jìn)行連接,若不存在或過期會(huì)向服務(wù)器獲取新token數(shù)據(jù)進(jìn)行連接,連接成功后將新Token緩存本地。
SDK具備自動(dòng)重連機(jī)制,在整個(gè)應(yīng)用全局只需要調(diào)用一次連接即可,連接異常斷開后會(huì)啟動(dòng)重連機(jī)制進(jìn)行多次重連,在這之后如果仍沒有連接成功,還會(huì)在當(dāng)檢測(cè)到設(shè)備網(wǎng)絡(luò)狀態(tài)變化時(shí)再次進(jìn)行重連。
心跳保活,為了保持客戶端和服務(wù)端的實(shí)時(shí)雙向通信,需要確保客戶端和服務(wù)端之間的TCP通道保持連接不斷開,IM連接成功后,SDK每間隔50秒會(huì)向服務(wù)器發(fā)送一個(gè)ping包,服務(wù)器接收到ping包后立即響應(yīng)一個(gè)pong包,如果服務(wù)在120秒內(nèi)檢查沒有收到過ping包會(huì)立即斷開此連接,釋放資源。SDK在檢測(cè)斷開后會(huì)自動(dòng)觸發(fā)重連機(jī)制。
發(fā)送方->接收方:ping
接收放->發(fā)送方:pong
5.總結(jié)
本文內(nèi)容介紹了之家IM即時(shí)通信平臺(tái)部分設(shè)計(jì)策略,借此機(jī)會(huì)總結(jié)設(shè)計(jì)方案及技術(shù)實(shí)踐,與大家一起學(xué)習(xí)提升。目前該項(xiàng)目在之家已經(jīng)落地兩年有余,接入十幾條業(yè)務(wù)線,包含單聊、群聊、聊天室、公眾號(hào)、通用信令服務(wù)等場(chǎng)景,日均服務(wù)三端用戶在千萬級(jí),為之家三端產(chǎn)品提供全雙工消息總線基礎(chǔ)設(shè)施支撐;目前一些個(gè)性化產(chǎn)品需求以及相關(guān)運(yùn)營平臺(tái)仍在不斷完善中,如果你對(duì)此很有興趣,歡迎加入我們。
作者簡(jiǎn)介
林道輝
■ C端及中臺(tái)產(chǎn)研中心-看選技術(shù)團(tuán)隊(duì)
■ 2012年加入汽車之家,目前主要負(fù)責(zé)參與熱聊業(yè)務(wù)及之家im通信平臺(tái)架構(gòu)及研發(fā)工作。
來源:微信公眾號(hào):之家技術(shù)
出處:https://mp.weixin.qq.com/s/kMGEpE_piFbeWTm9YxWVRA