熹樂科技範維肖CC:基於開源 YoMo 框架構建“全球同服”的 Realtime Metaverse Application

聲網發表於2022-12-18

前言

在「RTE2022 實時網際網路大會」中,熹樂科技創始人 & CEO @範維肖CC 以《基於開源 YoMo 框架構建“全球同服”的 Realtime Metaverse Application》為題進行了主題演講。

本文內容基於演講內容進行整理,為方便閱讀略有刪改。


圖片

大家好,我是熹樂科技的 C.C. 範維肖,我們公司的產品是開源的實時邊緣框架 YoMo。在過去的兩年中,很多 Metaverse 行業的開發者使用了我們的產品。這次就和大家分享一下過去的兩年中,我們在 Metaverse 領域的一些經驗和體會。

在過去的二十年,開發者已經非常習慣 RESTful 開發方式,API 非常的簡單,我們用類似於 JSON、PutBuffer 等方式作為資料結構來做傳輸,透過一個 GET 一個 POST 就能夠解決絕大多數的業務邏輯問題。這也形成了今天主流的「API 經濟」模型,它主要的邏輯就是使用者跟伺服器在發生互動。

圖片

但是在 Metaverse 領域當中,RESTful 方式受到了很大的挑戰。比如下圖中的場景:

圖片

無論是在一輛自動駕駛汽車上,還是戴著 VR、AR 跟我們的現實世界形成與虛擬世界的實時投影,過程中都有大量的資料需要進行計算,而這些資料往往不是結構化的資料。

01 傳統產品和 metaverse 的三個關鍵差異因素

在這一類 metaverse 場景中,和傳統的產品相比有三個重要的不同因素。第一個關鍵差異,是越來越多的資料從 JSON 變成了流式的資料 Streaming Data。

圖片

這當中一個明顯特點,是各種感測器在採集資料、傳輸資料。對於使用者而言,上行資料的量比下行資料的量要大,也就意味著越來越多的資料需要透過網路來進行共享,需要去尋找它的計算單元完成計算。這個情況和此前“下行資料遠遠高於上行資料”、計算離使用者很遠的情況是完全不一樣的。

第二個差異在於低時延成為了一個非常非常重要的因素。

圖片

像在剛才我們講的場景當中,可以大致分為三部分:

  • Video Stream
  • Audio Stream
  • Behavior Sequences

其中 Video Stream 主要應用在自動駕駛汽車、人臉識別當中;Audio Stream 是透過一條流來傳輸音訊,可用於各類實時翻譯、語音控制等場景;Behavior Sequences 是動作序列,連續的動作序列資料可以用於做規則判斷、模式識別、推薦引擎,以及欺詐檢測等等。這些都需要實時的完成計算。

第三個不同的點是整個 Metaverse 是一個全球化的模型,每一個人都在跟全球所有的人組成一個自己主導的虛擬世界,那麼每一個“我”與另一個人之間的 Metaverse 是相互融合在一起的,每個人都是自己世界的中心,這是 Metaverse 相關產品架構的底層邏輯。

圖片

那麼這也形成了一個與之前傳統來講最大的不同:以前是人與計算單元發生互動,但今天人與人之間在發生著劇烈的互動。這是我們過去兩年服務 Metaverse 行業開發者的過程中,一個最明顯的感受。

02 如何解決這些難題?

開源框架 YoMo 有一個最簡單的定位是 Streaming Serverless,讓開發者使用 Serverless 的模式作為程式設計正規化,構建整個的微服務的邏輯,解決流式的實時開發。

這個概念其實不新,在最早計算機出現的時候,程式間的通訊靠的就是 Unix Pipeline。

圖片

如上圖所示的程式中,把輸出放到左側 ls 命令的標準輸出中,透過 Unix Pipeline 以位元組流的方式,進行單向的向後傳遞,傳遞給右側的 wc 程式。透過這樣的方式,解耦了左側的 ls 和右側的 wc。

那麼 Unix Pipeline 就可以按照這樣的流程連續起來,用檔案描述服務去做整個的解耦和連線,這也是經典的 Unix 哲學中一個很重要的部分。

圖片

而像我們經常在命令列中透過用 cat 命令去列印內容,用 sort 去排序,用 uniq 去排除重複的資料,用 grep 去做過濾,這些應用是用一個豎線來表示整體的 Pipeline 的這個過程。

圖片

YoMo 就是基於這個思想,但是放大到了整個網際網路的級別來做。

現在我們來看下圖,如果我們的應用程式從左側的 sort 到 uniq,然後 sort 到最後的 head,這幾個命令我們需要去平衡它的計算成本和計算時延的需求。

圖片

那麼我們就可以把它分別部署在不同的位置,比如說最左側,我們可以把它部署在 5G MEC 上,這樣的 sort 就能夠達到很快的結果。然後我們可以依次來調整剩下的級別,放到城市級、國家級甚至整個大洲,就我們今天常規的雲端計算的節點上面。

這樣我們就能獲得更低的計算成本來構建應用,這使得不同的服務可以按照它的響應級別和成本控制的要求,去做平衡和取捨。這在傳統的分散式計算當中,要花很大的精力去構建如此的基礎設施。

這也引出來 YoMo 的三個核心概念 —— 資料來源、處理函式和 Zipper。

圖片

Zipper 就像 linux 的 Pipeline 功能一樣把兩側連線起來,去把資料調配到不同的計算資源。資料來源是用於把資料結構轉換成能在 YoMo 裡面去流動的資訊,這樣才能夠實現低時延、高效的全球傳輸。

計算的運算元可以把它理解為資料流動的方式,從左向右在做流動,那麼中間靠一個 Zipper,像衣服的拉鍊一樣,把所有的運算元和資料重合,每次重合就是一次計算。這樣最終能形成的架構是地理位置分散式的架構方式。

目前傳統在用的分散式都是在一個單一資料中心裡的分散式,但需要滿足全球使用者使用的時候,需要變為架構在今天的 IaaS 之上的全球分散式技術。

寫這樣的應用大家肯定會感到非常的痛苦,我們在離開 7 毫秒時延的約束,全球範圍都一兩百毫秒的時候,如何能保證我們的分散式的 CAP 理論一致性等等,都是相對棘手的難題。

所以 YoMo 的框架旨在於解決面向於全球分散式場景下,如何更簡單的構建自己的應用程式。那我們應用程式一旦構建完就可以部署在離使用者更近的地方,來為他附近的使用者提供低時延,並且成本更低廉的服務,這樣全球應用的平均時延可以從今天的 260 毫秒最佳化到全球小於 50 毫秒。

圖片

地理位置分散式是逃不開的話題,因為網路的時延和光速是成正比的。今天我們的網路在極限場景下,資料的傳輸速率跟距離成正比。

下面的幾張圖展示了當資料中心放到北京,在 10 毫秒、20 毫秒、50 毫秒的時延情況下,理論上能覆蓋的面積。

圖片

圖片

圖片

如圖所示,50 毫秒的時延理論上可以實現覆蓋亞洲和東歐的部分;100 毫秒的時延,如果將資料中心部署在美國的東部,理論上是可以覆蓋半個地球的,但實際環境中其實根本做不到這一點。

圖片

因為實際場景下,使用者從自己的端上到接入服務的鏈路非常長,而且業務提供方對此又不可控。這種情況下的問題就要糟糕很多,在很多基礎設施環節都需要做大量的最佳化。

很多公有云在不同的大洲都有多個資料中心,但跨區域的時候,這些資料中心之間的互動其實也是不夠理想的。這個時候要考慮的,是如何解決同一個雲上多資料中心、不同雲不同資料中心之間如何能高速的互動,並且能使得我們的應用能夠自我治理。

自我治理可以使得它不斷的繁殖。當一個區域的使用者越來越多的時候,我可以繁殖一個新的節點出來,這個節點是自適應、自組織的,並且能向上與之前的計算農場結合在一起。

這種自我治理的思路不是創新,也是來自於網際網路架構中非常傳統的基礎模型。Internet 其實就是 a network of networks,它就是由一個一個的網路組成,中間由 BGP 連起來,這也是 YoMo 架構的理念。

圖片

03 開發者友好性

YoMo 要花大量的精力去解決的第三個事情,是開發者友好性的問題。為什麼呢?想想我們今天的端,我們有很多做端遊的使用者,他們用 YoMo 來解決的第一個問題是 WIFI 網路的問題。

這背後的原因在於,目前我們大多數場景還在用 WIFI-5,其資料傳遞鏈路是波,而波是非常容易受到干擾的,比如說建築物的遮擋和多裝置之間的干擾,從而導致丟包。

圖片

在有丟包、時延產生的時候,TCP 吞吐量就會快速的下降,因此我們不得不去調整擁塞控制演算法。但擁塞控制演算法需要按照具體的應用來設定,做影片和做遊戲是完全不一樣的。加上鍊路中網路裝置僵化因素的存在,也使得使得我們對 TCP 的最佳化不一定能成立。比如說中間裝置很老不支援新的演算法,那麼 TCP 就會降級,降級到最原始、最落後的狀態。所以中間裝置的僵化其實是現階段全鏈路調優 TCP 過程中很難的一點。

但是去年,IETF 釋出了 RFC9000,就是 QUIC 協議。QUIC 基於 UDP,具備更好的安全性,今年釋出的 HTTP/3 底層的傳輸層就是 QUIC 協議。

圖片

QUIC 有各種優點,比如說它的多流非常的好,非常適合去開發複雜業務邏輯的應用,但是很難用。

如果大家去翻 QUIC 的 IETF 的文件會發現它是一個協議族,有一大堆的文件要讀,都讀透了才能充分的駕馭它,進而改造上層應用的程式碼去發揮 QUIC 的優勢。你會發現一會兒我要翻 QUIC 的東西,一會兒我要翻 QUIC 擴充套件的東西,非常麻煩。那麼如何能讓我們將 QUIC 應用到我們的應用裡邊變得非常容易?能否跟以前開發應用程式一樣還那麼簡單?那麼如何降低使用者的學習成本,這其實是 YoMo 在做的一個非常重要部分的工作。

下面這張圖程式設計師們也非常熟悉了,是著名的 Emacs 的蝸牛曲線。

圖片

我們降低學習成本的一個方式,就是藉助於 Serverless。Serverless 的開發正規化大家都已經非常的熟悉了,但 Serverless 到今天仍有一個致命的缺點,就是絕大多數的 Serverless 是無狀態的執行,按照執行時長計費,這使得 Serverless 涉及到一系列的問題,比如說沒有狀態的時候還是要把臨時狀態打到 DB 上。但在全球分散式系統裡,我們的 DB 又非常難去做全球讀寫,中心化的 DB 使得時延無法得到保障。

所以我們把 Serverless 升級了一下,把它先變成了 stateful。

圖片

如上圖中的函式所示。當拿到一個資料的時候,我們支援把它抽象成一個 Rx 的流,從而可以藉助很多 Rx 的方法去解決問題。比如說像這個例子當中,我要從類似於 VR 眼鏡這樣的感測器中傳資料,那麼我可以讓它每收到 50 個資料包做成一個 buffer,收到 50 個資料包後我再讓 echo 去計算。這在以前我們需要花費精力去做這種框架支援應用的快速開發,今天藉助 YoMo 會簡單很多。

同時,它要保持著以前 Serverless 的簡單易用特性。

圖片

目前, YoMo 的 Streaming Serverless 也支援了 Rust 語言,現在有越來越多的開發者在使用 Rust 語言去寫自己的後端,Rust 的生態也變得越來越好,這種語言有很多出彩的地方。

圖片

但 Rust 也相對難以管理。尤其我們還要考慮一個問題,就是目前的運算元都是在雲上進行,不管是在邊緣的雲上還是在傳統的公有云上。那有沒有可能把運算元拉到端上來執行?

比如說要考慮更好的資料安全,那麼如何來調配它?基於這一點,我們選擇了使用 WebAssembly 來做支援。

圖片

我們完全可以把 Serverless 函式變成 WebAssembly,那麼它就可以在 YoMo 裡面去被執行。

圖片

像上圖所示的 demo 中,可以把 rust 程式碼編譯成 wasm32-wasi 這樣的 target,然後用 YoMo run 然後把它執行起來。

圖片

我們也在跟 CNCF 的專案在合作,比如上面這個例子裡,就是 YoMo 與開源的 WasmEdge 打通,基於標準的介面,都是社群型的開源專案,使得開發者不用擔心被單一供應來源繫結的問題。

04 為前端開發者的特別準備

這兩年前端發生了很大的變化,但是開發工具並沒有發展得很快。舉個例子,過去的十幾年裡面吧,我們要想寫一些 Web 的實時應用,我們可選的工具並不多。WebSocket 可能是絕大多數人都在用的一個工具。但是 WebSocket 太老了,而且呢,WebSocket 有諸多的劣勢,尤其是針對於今天覆雜的應用程式而言。

在今年的年初,谷歌釋出了 WebTransport,現在 Chrome、Microsoft Edge 都已經做了支援,然後 Firefox 也正在去支援它,今天全球 70+% 的 Web 請求都已經支援它了,可是它的落地佔比卻還不足 0.1%。

圖片

我們能看到關於 WebTransport 的介紹,它其實就是一個使用 HTTP/3 協議的一個雙向的傳輸通道,它被設計就是為了要解決雙向通訊的問題。

圖片

其中提到的 Datagrams 就非常有意思,很多基於 Web 去做遊戲的人沒法用 UDP ,開發者就要花很大的精力去解決這個領域的問題,所以後來很多應用都不得不選擇去降級處理,大多都會選擇透過犧牲產品體驗的方式,就是因為技術上沒法滿足。

圖片

那今天有了像 Datagrams 的寶貝,我們就能像 UDP 一樣的去高速的去傳資料,這是給 Web 開發者引入了新的東西。

圖片

同樣,Streams API 也非常的強大。今天我們可以用來去操作位元組流,不需要去關注各種的物件的問題,我的音訊、影片,我的各種流式的編解碼器都能夠放到前端去做。

下面我們來看看 Streams API 的使用方式。

圖片

上圖所示是如何發資料到 WebTransport。能看到需要先建立一個 SendStream,然後拿到這個 Stream 要去 getWriter。第二行、第三行、第四行是要準備好我的資料要按照 Uint8Array 的形式準備好,然後要把它 write 過去,還要去看控制 error 的問題。

如果要接收讀取更費事了。

圖片

要讀的時候要先去建立一個 receiveStream,拿到他的 reader 後,要一直去 read 資料。但這個時候就有一個問題了,如果我的 server 和我的客戶端去互動的時候,我怎麼知道我的每一個資料包的邊界是什麼?像我連續的傳兩個 json 過去,我怎麼知道如何區分這兩個 json 什麼時候開始做反序列化?這些都使得前端的開發者不得不要自己去設計一些資料結構。

那麼這種非常底層,low level 的 API,這就像我們直接在用 TCP、用 UDP、用 QUIC 是一個道理,我們需要做大量的基礎工作來去支撐我們的上層建築的開發。

但 Strams API 有一個非常好的功能是他支援雙向流,那麼支援雙向流的時候呢,我們的開發邏輯就會變得更復雜了。我們一邊要控制 ReadableStream,一邊還要控制 WritableStream,往往我收到的資料要做一些工作,而我還要完成一些非同步的操作,這會使得我們的程式設計模型變得更加的複雜,尤其是業務邏輯複雜的時候,這個就非常難控制了。

那麼 WebTransport 雖然看起來使用方式很簡單,但是要做大型專案的時候,還是有困難的。我們可以在官方推薦的 WebTransport.day 上面去體驗一下 WebTransport 的速度如何。

圖片

在 WebTransport 之外,我們也是可以使用 YoMo 去寫一個 Serverless 的方式看到整個 Server 端的邏輯開發。做過前端實時通訊的同學一定都非常困惱當年我們去寫 WebSocket 的業務邏輯,比如說基於 SocketIO,要處理很多很多的問題,然後還可能要在 WebSocket 上做 RTC 類的資料等等。

體驗過後,能明顯感受到 WebTransport 的使用比 WebSocket 是難了很多的,那麼如何能讓 WebTransport 在 server 端的開發變得異常的容易,並且可以不去關心整個的網路層、流這些複雜的 API,只是簡單的就像前面的全球響應的模型一樣,去寫我們的程式碼。?同時我寫完的程式碼能不能分別部署在不同的區域裡邊,能使得就近去服務不同區域的使用者?

這些是可以藉助於 YoMo 來完成的。

圖片

進入 https://webtransport.day/serverless 頁面,我們可以去建立一個 serverless ,用 rust 來寫,然後編譯成一個 WebAssembly 檔案,用 YoMo 在本地執行起來。

這樣全球的使用者都可以把資料發到 YoMo 的開發者服務的節點上,這是一個免費的為開發者提供測試服務,這個服務會把資料推到你本機的 webAssembly 程式中去,執行並拿到資料的結果。

以上就是我今天跟大家的一些分享,這也是在過去的兩年裡邊我們服務了一些 Metaverse 產品的開發者後的經驗。這些開發者有的是做 VR 的、有的做 AR 的,有的基於 Web 在做遊戲和辦公協作(Collaborative SaaS),也有的是基於手機裝置和移動裝置來做 Metaverse 的遊戲應用等等。

針對於這些不同產品的構建方式以及複雜程度,我們在整個的開發者程式裡邊打磨出來的開發模式 Stream Serverless,可以基於 Streaming Stateful Serverless 的開發方式。

歡迎大家跟我們一起來打造未來實時全球網際網路的新浪潮!

相關文章