小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

系統(tǒng)設(shè)計 | 實時協(xié)作應(yīng)用的設(shè)計

 漢無為 2023-08-03 發(fā)布于湖北

同名知乎:少個分號

圖片


互聯(lián)網(wǎng)時代越來越多的實時協(xié)作軟件出現(xiàn),例如在線點餐、文檔編輯、在線繪圖等。

今天來聊聊這些場景一般如何實現(xiàn)的。

場景和問題

實時協(xié)作軟件一般用于多個人同時操作(也包括一個人多個會話)。例如 Google Doc 可以支持同時編輯文檔,并將多人編輯的結(jié)果合并到一起展示,而且能相互看到其它人的操作。

但是,在實現(xiàn)過程中會有非常多的技術(shù)問題和業(yè)務(wù)邏輯問題需要考慮:

  1. Web 平臺如何建立長連接?

  2. 如何進(jìn)行一致性處理,讓多人編輯的結(jié)果盡量不沖突?

  3. 如何支持離線操作?

  4. 如何擴(kuò)容?

  5. 有那些框架?

Web 平臺如何建立長連接?

建立長連接的技術(shù)從遠(yuǎn)古互聯(lián)網(wǎng)技術(shù)發(fā)展開始就有很多方案(有些方案現(xiàn)在很多人都不會再聽到了)。

建立 Web 長連接我們一般可以:

  1. 定時重試:比如每隔 60秒發(fā)起一次 HTTP 請求,這是最差的一種方案。

  2. HTTP 長連接(Comet):前端發(fā)起一個 HTTP,后端掛起,在沒有信息回填之前掛起請求,前端如果超時,自動重連再發(fā)送一個 HTTP 請求。

  3. WebSocket:通過 HTTP 握手,然后建立(Upgrade 過程)一個 TCP 連接。代表框架 Socket.IO,可以支持使用 WebSocket 和 Comet 建立連接。

  4. MQTT 協(xié)議,或者其它消息協(xié)議:提供一些消息持久化、QoS(根據(jù)服務(wù)質(zhì)量,選擇重傳的策略) 的支持。

  5. Flash、Silverlight 等瀏覽器富應(yīng)用運行平臺。這也是古老的互聯(lián)網(wǎng)技術(shù),這兩個平臺目前都已經(jīng)宣布停止維護(hù),優(yōu)先推薦使用 H5 相關(guān)技術(shù)。

  6. 瀏覽器插件。某些廠商對于專業(yè)應(yīng)用有更高的要求,所以會實現(xiàn)自己的協(xié)議,根據(jù)原生 Socket 進(jìn)行連接,并通過插件的方式和瀏覽器集成,為 Web 提供更基礎(chǔ)的 API。

當(dāng)前主流的方案一般是 WebSocket。

如何進(jìn)行一致性處理?

相比網(wǎng)絡(luò)連接的問題,如何讓多人編輯的結(jié)果盡量不沖突這個問題更難。

不同的場景、數(shù)據(jù)類型可以采用的策略并不相同,下面以文章開頭的幾個例子說明如何實現(xiàn)一致性。

點餐的場景下如何處理一致性?一般將業(yè)務(wù)操作原子化+冪等,把數(shù)據(jù)更新修改為加、減操作,使用最終一次性讓服務(wù)器決策結(jié)果(發(fā)生沖突時,一般是先到先做,后到丟棄策略),并將事件分發(fā)到參與方。

在線繪圖場景如何實現(xiàn)一致性?抽象圖的數(shù)據(jù)結(jié)構(gòu),使用節(jié)點和邊對圖進(jìn)行結(jié)構(gòu)化處理,以節(jié)點和邊為原子單位,利用數(shù)據(jù)庫的能力高速更新。發(fā)生沖突時,可以使用后到覆蓋的策略,后到的更新會覆蓋前一次的更新??梢允褂靡恍┓顷P(guān)系型數(shù)據(jù)庫的 upset 能力,將插入和更新合并處理。

PS:對于圖數(shù)據(jù)庫的選擇,可以使用 Orientdb、MongoDB、Neo4J 等數(shù)據(jù)庫來實現(xiàn)。

在線文檔編輯場景如何實現(xiàn)一致性?可以使用 OT 算法(另外一種算法叫做 CRDT,CRDT 可以看做 OT 算法的拓展),OT 算法使用偏移量作為更新依據(jù),可以快速合并協(xié)同者的數(shù)據(jù)內(nèi)容。

某種程度上來說,文檔結(jié)構(gòu)和圖的結(jié)構(gòu)非常類似,因此可以使用非關(guān)系型數(shù)據(jù)庫的特點盡可能地提高性能。

不管什么一致性策略,時間久了都會不一致,在游戲場景和一些協(xié)作算法中會使用一個叫影子跟隨的策略定期抹掉各個客戶端的差異。其原理是定期或者網(wǎng)絡(luò)連接中斷后,重新和服務(wù)器對齊版本,把服務(wù)器的最新版本往客戶端拉取。

如何支持離線操作?

離線操作在實時協(xié)作系統(tǒng)是一個非常費力不討好的特性,因為總是會導(dǎo)致用戶數(shù)據(jù)丟失,而且非常難以探查問題。

以 MQTT over Socket 為例,如果要實現(xiàn)實時協(xié)作,可以考慮如下方案。

  1. 先把離線過程中的變化記錄下,網(wǎng)絡(luò)連接后發(fā)送到后端,并廣播出去。這個方案會記錄很多過時的操作數(shù)據(jù),比如上周協(xié)作了一次,中間其他成員協(xié)作,今天線上會播放整周的數(shù)據(jù),而且還會存在服務(wù)器上,會產(chǎn)生大量的沖突。

  2. 本地操作不記錄變化,網(wǎng)絡(luò)連接后只發(fā)送一個快照版本,服務(wù)器根據(jù)某種策略接收這個快照版本的數(shù)據(jù)或者部分?jǐn)?shù)據(jù)。

一般優(yōu)先推薦使用方案 2,這樣在版本比較時更可控,甚至可以允許用戶確認(rèn)兩個版本的差異,并根據(jù)某種策略合并。

另外需要注意,離線后重新上線需要使用類似影子跟隨的方式,獲取服務(wù)器最新的版本。(因為服務(wù)器總是要保存一份最新版本數(shù)據(jù))。

如何擴(kuò)容?

實時協(xié)作系統(tǒng)不具備天然的水平擴(kuò)容能力,需要設(shè)計相關(guān)機(jī)制進(jìn)行擴(kuò)容。

擴(kuò)容方式一般有兩種:

  1. 將用戶隔離到小規(guī)模范圍內(nèi)的協(xié)作范圍中。

  2. 將用戶放到一個大池子,對事件交換機(jī)制進(jìn)行擴(kuò)容。

我把他們叫做集中式擴(kuò)容和分散式擴(kuò)容。

集中式擴(kuò)容有點像吃大鍋飯,對用戶群不區(qū)分,而是對事件分發(fā)的服務(wù)器進(jìn)行水平擴(kuò)容。

下面是 Socket.IO 提供的解決方案:

圖片

反過來看分散式擴(kuò)容,如果我們根據(jù)一些業(yè)務(wù)策略將用戶 stick 到具體的服務(wù)器上,讓這些用戶在服務(wù)內(nèi)部完成事件交換,即使這些服務(wù)器在一定程度上是有狀態(tài)的。

分散式擴(kuò)容更像是游戲服務(wù)器模式,避免將消息廣播到太大范圍,因為我們在業(yè)務(wù)上總是能找到消息廣播的主題,讓廣播的范圍盡可能小,這樣系統(tǒng)崩潰時影響的用戶范圍比較小。

有那些框架可以幫助簡化實時協(xié)作的工作?

從零開始實現(xiàn)一套實時協(xié)作系統(tǒng)比較困難,而且需要長期探索一些技術(shù)選型的問題。

這里分享一些常見的技術(shù)方案和框架作為參考。

  • Convergence:Convergence 是一款專門為實時應(yīng)用設(shè)計的框架,主要技術(shù)選型有:Scala、Akka、OrientDB、Google Protocol Buffers、Orient DB。從技術(shù)選型上可以看出,實時應(yīng)用需要高并發(fā)、響應(yīng)式編程、圖數(shù)據(jù)庫等特性的能力。

  • Socket.IO: Socket.IO 是一個基于 WebSocket 和事件的網(wǎng)絡(luò)庫,用于實現(xiàn)消息推送等需求。

  • MQTT:MQTT 是一款非常熱門的物聯(lián)網(wǎng)連接協(xié)議,它具有無連接、異步消息、QoS 保證等特點。常見的實現(xiàn)有 EMQX、HiveMQ 等。

從需求匹配性上來說,Convergence 就是為了實時應(yīng)用設(shè)計的,它有很多 Demo,包括在線協(xié)同編程、文檔協(xié)同編輯、協(xié)同繪圖等。借助 Akka 的分布式能力,Convergence 也支持水平拓展的集群部署。

Convergence 的缺點是它是一個完整的應(yīng)用,而不是一個庫,且是 Scala 編寫的,需要學(xué)習(xí)相關(guān)的語言特性。

而 Socket.IO 做的事情就少很多,Socket.IO 只提供網(wǎng)絡(luò)連接、事件分發(fā)等任務(wù),默認(rèn)情況通過 Websocket 進(jìn)行通信,在瀏覽器版本過低時也支持 HTTP 長連接,也就是 COMET 技術(shù)。

Socket.IO 提供了 Java、Nodejs 等平臺和語言的實現(xiàn),所以更容易集成到自己的應(yīng)用中來。

默認(rèn)情況下 Socket.IO 在內(nèi)存中實現(xiàn)消息轉(zhuǎn)發(fā),也可以接入集中的數(shù)據(jù)源或者事件 Adapter 來完成消息廣播的能力。

常用的有:

  • Redis Streams adapter

  • MongoDB adapter

  • AMQP (例如 RabbitMQ)

圖片

圖片來源:https:///docs/v4/adapter/

實時協(xié)作應(yīng)用設(shè)計上的注意事項

有一些實踐上的坑不得不提一下。

用戶數(shù)據(jù)丟失幾乎是必然的。

這一點主要還是 CAP 定理約束,在 系統(tǒng)設(shè)計 | 分布式事務(wù)場景、概念和方案整理(含概念圖) 中我們討論過這個話題,而在實時協(xié)作應(yīng)用中這種問題變得尤為突出。

用戶離線后即使開啟高的 QoS 保證消息最終發(fā)送到用戶,但是當(dāng)用戶最終收到消息后,現(xiàn)場可能已經(jīng)發(fā)生變化,所以這甚至帶來一些副作用。

不要過于依賴歷史消息。

為了保證用戶的數(shù)據(jù)安全,我們可能會開啟 QoS 保證,很多通信框架都會通過確認(rèn)的方式保證送達(dá)事件。

高的 QoS 不僅影響性能而且對一致性幫助不大,因為和上面提到的類似,歷史消息對最終結(jié)果意義不大。

本地實現(xiàn)Undo、Redo 操作

我們有時候會設(shè)置 Undo、Redo 操作來實現(xiàn)撤回和重做,但是一定不要將這兩個事件廣播出去,而是應(yīng)該在本地完成后,作為新的操作事件發(fā)送出去。

例如 Undo 在本地表現(xiàn)為刪除一段文本,那么發(fā)送到服務(wù)器的消息應(yīng)該是刪除一段文本。

合理設(shè)置心跳檢測機(jī)制

通信框架都會使用心跳來檢測離線,默認(rèn)情況下部分框架的心跳設(shè)置非常長,可能不能滿足某些場景需要,可以設(shè)置更短的心跳。

但是,心跳一般是網(wǎng)絡(luò)協(xié)議的職責(zé),盡量不要在應(yīng)用中再實現(xiàn)一次。

隨處可見的非阻塞式編程。

實時協(xié)作往往需要非常高的并發(fā)處理能力,一旦在代碼中需要異步處理的地方出現(xiàn)阻塞,整個系統(tǒng)的性能就會急劇下降,而且比較難以排查。

我們可以采用一些非阻塞式的框架或者庫提高響應(yīng)式編程的體驗,例如 RxJava、RxJS 等。

編程語言和平臺影響很大

有一些語言的并發(fā)能力天生就很強,比如 elixir、Erlang/OTP、Scala、Nodejs 等。這些編程語言或者平臺往往都是非阻塞式的,而 Java 一般來說主要應(yīng)用于業(yè)務(wù)系統(tǒng),對于需要高并發(fā)的場景來說,有能力的話嘗試其它語言可以收獲非常多(我曾經(jīng)將 MQTT 服務(wù)器切換為 EMQX 后獲得性能上的飛躍提升,不過其構(gòu)建在 Erlang/OTP 之上,非常遺憾的是,完全沒有能力對其源碼進(jìn)行拓展)。

參考資料

[1] The free and open source engine for real-time collaboration https:///

[2] Socket.IO 文檔 https:///docs/v4/adapter/

[3] Building Real-time Applications with Phoenix & Elixir https://www./courses/building-real-time-applications-phoenix-elixir

[4] Building real-time collaboration applications: OT vs CRDT https://www./blohttps://raw./linksgo2011/shaogefenhao-v2/master/src/posts/architecture//real-time-collaboration-ot-vs-crdt/

[5] Comet (programming) https://en./wiki/Comet_(programming)

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多