国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
系統(tǒng)設(shè)計(jì) | 實(shí)時(shí)協(xié)作應(yīng)用的設(shè)計(jì)

同名知乎:少個(gè)分號(hào)


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

今天來(lái)聊聊這些場(chǎng)景一般如何實(shí)現(xiàn)的。

場(chǎng)景和問(wèn)題

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

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

  1. Web 平臺(tái)如何建立長(zhǎng)連接?

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

  3. 如何支持離線操作?

  4. 如何擴(kuò)容?

  5. 有那些框架?

Web 平臺(tái)如何建立長(zhǎng)連接?

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

建立 Web 長(zhǎng)連接我們一般可以:

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

  2. HTTP 長(zhǎng)連接(Comet):前端發(fā)起一個(gè) HTTP,后端掛起,在沒(méi)有信息回填之前掛起請(qǐng)求,前端如果超時(shí),自動(dòng)重連再發(fā)送一個(gè) HTTP 請(qǐng)求。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如何支持離線操作?

離線操作在實(shí)時(shí)協(xié)作系統(tǒng)是一個(gè)非常費(fèi)力不討好的特性,因?yàn)榭偸菚?huì)導(dǎo)致用戶數(shù)據(jù)丟失,而且非常難以探查問(wèn)題。

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

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

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

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

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

如何擴(kuò)容?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

常用的有:

  • Redis Streams adapter

  • MongoDB adapter

  • AMQP (例如 RabbitMQ)

圖片來(lái)源:https://socket.io/docs/v4/adapter/

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

有一些實(shí)踐上的坑不得不提一下。

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

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

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

不要過(guò)于依賴歷史消息。

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

高的 QoS 不僅影響性能而且對(duì)一致性幫助不大,因?yàn)楹蜕厦嫣岬降念愃?,歷史消息對(duì)最終結(jié)果意義不大。

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

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

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

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

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

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

隨處可見(jiàn)的非阻塞式編程。

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

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

編程語(yǔ)言和平臺(tái)影響很大

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

參考資料

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

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

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

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

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

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
MQTT, XMPP, WebSockets還是AMQP?泛談實(shí)時(shí)通信協(xié)議選型
Socket.io
PHP消息推送的探討
使用openSSL構(gòu)造一個(gè)支持https的nodejs服務(wù)器
六款優(yōu)秀的開(kāi)源協(xié)作編輯工具
編程語(yǔ)言七牛云存儲(chǔ) - 七牛云 移動(dòng)端直傳 PHP服務(wù)器
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服