我用Rust實(shí)現(xiàn)的長連接方案

在上一篇文章阅悍,我們講到了長連接常見的實(shí)現(xiàn)方案致开,相信大家對(duì)長連接已經(jīng)有一定的了解了,這篇文章我們會(huì)講 FeatureProbe 的長連接實(shí)現(xiàn)方案艇潭。

一、為什么FeatureProbe需要長連接

Feature Toggle 在部分場(chǎng)景下戏蔑,客戶端對(duì)實(shí)時(shí)性有較高的要求蹋凝,如緊急情況,希望配置立刻下發(fā)生效总棵。有的 Feature 在 Web 端加載或 App 啟動(dòng)的時(shí)候就要讀取到開關(guān)的值鳍寂,雖然緩存能解決一部分問題,但是最快拿到最新的值彻舰,會(huì)更符合用戶的預(yù)期。我們?cè)谏掀刑岬竭^候味,長連接可以解決數(shù)據(jù)推送和請(qǐng)求優(yōu)化這兩個(gè)場(chǎng)景刃唤。

1、可選協(xié)議

  • SSE :Server Send Event 能滿足服務(wù)端向客戶端發(fā)送數(shù)據(jù)的需求白群,協(xié)議簡(jiǎn)單尚胞,但因?yàn)椴皇请p工的數(shù)據(jù)通路后期無法實(shí)現(xiàn) HTTP 的請(qǐng)求優(yōu)化。
  • TCP :目前最主流的長連接協(xié)議帜慢,配合 TLS 1.3 可以做到很好的使用效果笼裳。
  • QUIC :本身握手和 TLS1.3 融合,還支持連接恢復(fù)粱玲,多Stream避免包頭阻塞問題躬柬,有很多優(yōu)勢(shì),因?yàn)榛赨DP抽减,可能會(huì)有部分特殊網(wǎng)絡(luò)環(huán)境被禁止允青。
  • UDP :需要自己實(shí)現(xiàn)丟包重傳,部分網(wǎng)絡(luò)環(huán)境有可能被限制卵沉。
  • WebSocket :對(duì)瀏覽器友好颠锉,小程序唯一支持的雙向收發(fā) (全雙工) 協(xié)議法牲,很難做連接優(yōu)化。

2琼掠、設(shè)計(jì)目標(biāo)

  • 盡可能支持更多的端拒垃,小程序,移動(dòng)端瓷蛙,多種語言服務(wù)端悼瓮;
  • 盡量降低 SDK 的實(shí)現(xiàn)復(fù)雜度,方便后期社區(qū)貢獻(xiàn)速挑;
  • 盡可能使開關(guān)快速生效谤牡;
  • 盡可能低的數(shù)據(jù)傳輸量。

二姥宝、FeatureProbe長連接方案

1翅萤、協(xié)議選擇 WebSocket

小程序是我們一期要優(yōu)先支持的平臺(tái),所以所有不支持小程序的協(xié)議都不在一期的考慮范圍內(nèi)腊满。

  • 優(yōu)點(diǎn):是可以支持小程序和瀏覽器環(huán)境套么,小程序是我們優(yōu)先要支持的部分,在國內(nèi)的重要性非常高碳蛋,很多創(chuàng)業(yè)團(tuán)隊(duì)甚至只開發(fā)小程序的 APP 版本胚泌。
  • 缺點(diǎn):是連接建立的優(yōu)化很難進(jìn)行.在國內(nèi)網(wǎng)絡(luò)環(huán)境整體較好的情況下,大部分的請(qǐng)求還是在較快的響應(yīng)范圍之內(nèi).我們可以在后面二期的時(shí)候再針對(duì)其他端做多協(xié)議切換肃弟。

我們?cè)? Websocket 的基礎(chǔ)上進(jìn)一步選擇了 Socektio 這個(gè)網(wǎng)絡(luò)庫:

  • 優(yōu)點(diǎn):是在 WebSocket 的基礎(chǔ)上提供了斷開重連玷室,發(fā)送緩沖,消息確認(rèn)笤受,廣播穷缤,整體的編解碼邏輯簡(jiǎn)單,提供了長輪詢(long polling)的回退方案箩兽,在不支持 WebSocket 的設(shè)備上也能兼容津肛。

  • 缺點(diǎn):客戶端有限,老項(xiàng)目已經(jīng)比較成熟汗贫,目前已經(jīng)不太活躍身坐。

2、服務(wù)端推送

FeatureProbe Server 發(fā)現(xiàn)開關(guān)更新后落包,發(fā)送事件給關(guān)心這個(gè)開關(guān)的連接部蛇,對(duì)端的 SDK 收到事件,觸發(fā)一次開關(guān)拉取咐蝇。這里面能做的優(yōu)化是直接下發(fā)開關(guān)的值搪花,因?yàn)?Server SDK 和 Client SDK 的處理邏輯不同,我們放到下個(gè)迭代優(yōu)化。

  • 如何發(fā)現(xiàn)變化:開關(guān)的規(guī)則是存儲(chǔ)在 FeatureProbe API 服務(wù)中的撮竿,目前 FeatureProbe Server 通過接口周期性訪問得到吮便,直觀的想法是輪詢時(shí),去 diff 開關(guān)的值幢踏,就可以發(fā)現(xiàn)變化髓需,但是效率比較低。因?yàn)?SDK 是針對(duì)項(xiàng)目環(huán)境下所有的開關(guān)進(jìn)行獲取房蝉,這里環(huán)境的 SDK KEY 拉取整體的開關(guān)規(guī)則時(shí)僚匆,添加一個(gè) version 就可以判斷兩次之間是否一致。

  • 如何表示 SDK 對(duì)某個(gè)開關(guān)感興趣: 目前 SDK 向 Featureprobe Server 獲取開關(guān)搭幻,是以 SDK_KEY 為粒度的咧擂。在 SocketIO 連接建立后,SDK 會(huì)向 Server 注冊(cè) SDK_KEY, Server 就可以把這個(gè)連接存儲(chǔ)在相同 SDK KEY 的列表中檀蹋,等有開關(guān)發(fā)生變化松申,Server 知道開關(guān)是發(fā)生在哪個(gè) SDK_KEY 中,把 對(duì)應(yīng) SDK_KEY 列表中所有的連接都發(fā)送一個(gè)更新事件俯逾,就完成了變更的通知贸桶。實(shí)際實(shí)現(xiàn)利用了SocketIO 提供了 Room 的概念,僅需把連接和 SDK KEY做一下關(guān)聯(lián)桌肴,變更時(shí)直接對(duì) SDK_KEY 發(fā)送事件就可以了皇筛。

代碼示意:

import { createServer } from "http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer);
io.on("register", (sdk_key, socket) => {
socket.join(sdk_key);
});
httpServer.listen(3000);
// notify clients 
io.to(SDK_KEY).emit("update");

3、客戶端接收

FeatureProbe SDK 目前是 pull 模式和服務(wù)端通信坠七,即啟動(dòng)后通過輪詢來周期性獲取全量開關(guān)的數(shù)據(jù)水醋。在 SocketIO 的幫助下,添加 push 的模式很簡(jiǎn)單彪置。在原有基礎(chǔ)上初始化 SocketIO 的客戶端拄踪,連接建立后把 SDK KEY 發(fā)送給 Server, 然后監(jiān)聽一個(gè) Server 下發(fā)的 update 事件,收到事件就立刻觸發(fā)一次開關(guān)全量的拉取悉稠。斷開重連宫蛆,心跳艘包,回調(diào)等都交給 SocketIO 來做的猛。這里有個(gè)優(yōu)化是下發(fā)的數(shù)據(jù)可以是開關(guān)變更的數(shù)據(jù),而不僅僅是變更事件想虎,這個(gè)也是我們后續(xù)準(zhǔn)備做的工作卦尊。

三、最終實(shí)現(xiàn)

FeatureProbe Server 是 Rust 語言實(shí)現(xiàn)的舌厨,考慮到后續(xù)的性能和擴(kuò)展性等原因岂却,我們不想再引入一個(gè) nodejs 的模塊專門做長連接的管理,所以我用 Rust 實(shí)現(xiàn)了 SocketIO 的服務(wù)端 socketio-rs(實(shí)現(xiàn)的rust方案已經(jīng)開源到GitHub,點(diǎn)擊socketio-rs可訪問)躏哩,實(shí)際的 FeatureProbe 客戶端業(yè)務(wù)代碼服務(wù)端業(yè)務(wù)代碼都相對(duì)比較簡(jiǎn)潔署浩。

目前FeatureProbe 使用 Apache 2.0 License 協(xié)議已經(jīng)完全開源。你可以從 GitHubGitee 上搜索FeatureProbe獲取到所有源代碼扫尺。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筋栋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子正驻,更是在濱河造成了極大的恐慌弊攘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姑曙,死亡現(xiàn)場(chǎng)離奇詭異襟交,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伤靠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門捣域,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人醋界,你說我怎么就攤上這事竟宋。” “怎么了形纺?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵丘侠,是天一觀的道長。 經(jīng)常有香客問我逐样,道長蜗字,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任脂新,我火速辦了婚禮挪捕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘争便。我一直安慰自己级零,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布滞乙。 她就那樣靜靜地躺著奏纪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斩启。 梳的紋絲不亂的頭發(fā)上序调,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音兔簇,去河邊找鬼发绢。 笑死硬耍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的边酒。 我是一名探鬼主播经柴,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼墩朦!你這毒婦竟也來了口锭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤介杆,失蹤者是張志新(化名)和其女友劉穎鹃操,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體春哨,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荆隘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赴背。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椰拒。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凰荚,靈堂內(nèi)的尸體忽然破棺而出燃观,到底是詐尸還是另有隱情,我是刑警寧澤便瑟,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布缆毁,位于F島的核電站,受9級(jí)特大地震影響到涂,放射性物質(zhì)發(fā)生泄漏脊框。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一践啄、第九天 我趴在偏房一處隱蔽的房頂上張望浇雹。 院中可真熱鬧,春花似錦屿讽、人聲如沸昭灵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烂完。三九已至,卻和暖如春衩婚,著一層夾襖步出監(jiān)牢的瞬間窜护,已是汗流浹背效斑。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工非春, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓奇昙,卻偏偏與公主長得像护侮,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子储耐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容