釘釘協同引擎與應用場景技術探索

阿里巴巴移動技術發表於2022-03-30

作者:孫然(煮蝦)

協同引擎是釘釘面向跨平臺終端並解決分散式資料一致性的 Runtime 與開發框架。

它主要解決三類場景問題:

  • 多人實時協同
  • 跨端同步與應用狀態接力
  • 離線可用 Local First

同時,它也是面向開放的。一方產品可以用,三方開發者(小程式、H5 應用)也可以用。

協同引擎Demo Show

多人實時協同:一起標註

從釘釘客戶端 6.0.0 開始,訊息會話裡的圖片新增了“一起標註”功能。群成員可以對一張圖片進行同時勾畫,並且所有人都能看到其它人的實時筆跡:

在這裡,協同引擎 SDK 提供了一套 CoCanvas(協同畫板)元件,圖片訊息通過引用 CoCanvas 元件快速組裝出多人協同能力。除了解決多人實時資料(筆跡資料)的協同問題,協同引擎還提供了當前正在協同的參與者資訊,用於業務實現展示諸如“多少人正在標註”資訊的功能。

跨端同步:聊天草稿

你是否有遇到過這樣的場景:手機上編輯到一半的東西,回到電腦前想繼續編輯?或者,手機上截了個圖,要在電腦上繼續編輯。現在看來,你得在手機上先把資訊或圖片發給自己,然後再在電腦裡下載下來繼續操作。整個流程會被跨端傳輸過程打斷。

如果用協同引擎,整個流程或許可以變成這樣——你可以實現端到端的輸入同步:

或者在一端複製,直接在另一端貼上:

實現手機端和電腦端一系列連貫操作的無縫銜接!

在上面的例子中,協同引擎提供了 CoString、CoMap、CoList 等基礎資料結構,CoImage、CoClipBoard 等元件,讓上層業務共享資料就像讀寫本地變數一樣簡單。業務只需要關心業務本身需要處理哪些資料,而無需關心跨端需要額外做些什麼。未來協同引擎也可以繼續提供諸如 CoCamera、CoAlbum 等高階元件,讓桌面端應用可以實現拉起手機相簿選圖、拉起手機相機拍照等更高階的功能。

跨端同步,是讓同一使用者的多臺物理裝置,變成一臺統一的邏輯裝置,共享資料、共享系統裝置、共享應用狀態。由於協同引擎本身已經具有了最基本的資料同步功能,所以也能夠輕鬆支援這些需求場景。

面向開放:三方應用如何實現跨端接力

協同引擎作為跨平臺底層引擎同時也賦能與三方應用,助力實現:

  • 一次開發多端執行:作為三方應用跨端協同的載體,開發一套程式碼多端執行(移動/桌面)的小程式
  • 桌面端大屏生產力:桌面端小程式自動適配為大屏模式,充分發揮桌面端差異化大屏生產力優勢
  • 多人協同:基於協同引擎,實現多人任務協作
  • 跨端接力:基於協同引擎,實現跨端應用接力:手機上應用操作狀態,自動接力到桌面端大屏開啟
  • 離線可用:Local First。基於協同引擎,資料都在本地,任務亦可離線提交,協同引擎會確保任務最終成功
  • Backend As A Service:所有資料(同步、協同、接力)基於協同引擎,開發者只需寫前端程式碼,無須開發服務端

這裡面協同引擎做了什麼?

  • 作為小程式資料層,Backend As A Service
  • 多人編輯操作的資料實時協同
  • 跨端資料同步,應用狀態遷移接力

協同引擎簡介

協同引擎是【面向跨平臺終端的】【解決分散式資料一致性的】【Runtime 與開發框架】。

解決的問題

協同引擎主要解決三類場景問題:

  • 多人實時協同
  • 跨端同步與應用狀態接力
  • 離線可用 Local First

以上三類問題,即便不使用協同引擎,也有其他實現方式。但這些實現方式對於業務方而言,要處理很多“協同”領域的底層工程問題乃至演算法問題,例如網路處理、本地資料儲存、長時間離線處理、多人實時操作合併、回滾與衝突解決等。

協同引擎作為開發框架,提供了通用的協同能力,並以協同變數/元件的接入方式解決上述問題:

  • 宣告式使用資料。業務方直接使用協同變數,就像使用本地變數一樣,可以無須關注底層的操作合併、回滾、衝突解決等問題。
  • 跨平臺實現,全平臺可用。讓各端(Android/iOS/Windows/Mac/端外web)、各種形態(Native/H5/小程式)的應用都可以使用協同能力。

API與基本概念

協同引擎在上層的開發框架中提供了一套協同資料結構和 API。它們和普通的容器變數相似,但是卻自帶了協同能力。例如一個雲協同的計數器就可以這樣通過 CoCounter 協同變數解決:

Container container = Loader.getContainer(url);
CoCounter counter = container.getCoCounter("my_counter");

// 點選+1按鈕時
counter.add();

// 監聽資料變化
counter.addEventListener(new CoCounterValueChangedListener() {
    @Override
    public void onValueChanged(int newValue) {
        // 更新UI
        updateView(newValue);
    }
});

這裡,我們提出了幾個基本的概念

CDS

Collaborative Data Structure,協同資料結構。一個 CDS 物件即一個協同資料變數。

CDS 也有不同的型別,例如 CoString、CoBoolean、CoMap、CoList,顧名思義對應了程式語言中常用的基礎資料型別及集合型別。

當然也有更“複雜”的資料型別,例如 CoText(支援 OT 的文字型別)、CoPixel(圖形標註型別)。

Container

一組 CDS 物件的集合。同一個 Container 中的 CDS 物件可以互相引用,例如 CoList 中的某個元素是 Container 中另一個 CoString 物件。

開發者只需要像使用自己熟悉的資料結構一樣用協同變數開發業務,就能輕鬆實現資料協同。

內部架構1客戶端協同引擎客戶端自上而下主要分為以下幾層:Platform:各平臺提供面向開發者的 API 層API:跨平臺膠水層Loader:負責載入 Container 的單例模組Container:協同引擎跨平臺模組核心,負責 CDS 管理和各項引擎執行時必要流程Service:協同引擎依賴的平臺層能力介面Provider:各平臺實現 Service 層介面的能力2服務端\
協同引擎服務端的職責相對少一些,主要負責連線和會話的管理、訊息廣播、定序和落庫,同時也會有操作變換。

更多用武之地

除了 Demo Show 中的應用場景,還有更多的可能性……

更多的“一起XXX”

除了已有的“一起標註”,還有很多諸如“一起玩”、“一起聽”、“一起看”等等更多的“一起XXX”的場景。在這些場景中,開發者所遇到的資料協同相關的問題都會有很多交集,想必都能用一套協同引擎來解決。

弱網離線優化

這個話題看似與協同關係不大,但協同引擎自帶的 Local First 屬性已經保障了弱網和離線下的可用性。許多弱網離線優化需要做的事情,協同引擎已經做過了。

那麼協同引擎是如何做到弱網離線可用的呢?

離線可用性

協同引擎內含一個快取佇列——PendingQueue,它負責快取所有服務端未確認的本地操作(op)。當業務操作協同資料結構時,會產生一個操作,協同引擎首先會將其快取在 PendingQueue 中並落庫。PendingQueue 中的操作會按先來後到的順序依次傳送,直到操作被服務端確認後才會傳送下一個。在每次協同引擎初始化時,也會將數 PendingQueue 從本地資料庫恢復。所以在協同引擎中,資料的產生和恢復,都是經歷先本地落庫、再傳送等待服務端確認這個過程的。這就是所謂的 Local First,保證了協同引擎的離線可用性。

弱網可用性

首先,協同引擎會感知網路連通性。當明確網路不連通時,會暫停 PendingQueue 的傳送操作;網路連通後會再自動開啟傳送機制。

其次,在網路連通時,不論出於什麼原因,只要傳送的操作在一定時間內(如 5 秒內)如果沒有收到服務端的確認,協同引擎就會重新傳送這個操作,直至服務端確認為止。這就保障了協同引擎在弱網下的可用性。

對比

下面的表格對比了弱網離線優化相關工作與協同引擎中已有的一些機制:

可以看出,大多在弱網離線優化中需要做的事情,協同引擎都已經具備相應能力了。協同引擎最初的設計已經符合了弱網離線可用的主要要求,並且保障操作永不丟失,亦可用於弱網離線優化的相關工作中。

總結

本文介紹了協同引擎框架,它致力於解決多人多端資料協同的問題,讓業務輕鬆實現多人協作的功能。我們列舉了幾個直觀的 Demo,然後探討了一些其它應用場景,除了能夠應用於各種”一起XXX“的業務,還能用於解決跨端資料接力問題和弱網離線優化工作。

關注【阿里巴巴移動技術】微信公眾號,每週 3 篇移動技術實踐&乾貨給你思考!

相關文章