WebAssembly 開啓微服務新時代?

整理 | 丁廣輝       責編 | 張紅月

出品 | CSDN(ID:CSDNnews)

如果從微服務的功能定義開始,很可能把這種模式定義爲通過網絡進行通信的 REST 服務。但當談到編寫微服務的程序時,有一個嚴峻的現實擺在面前,創建微服務的第一步需要涉及大量的代碼。雖然已經不在考慮這個問題,僅僅是將這些代碼的存在作爲微服務是一個 “框架” 的理由,卻也因此忽略了它對開銷、運行時間、要求、安全性、成本和可維護性的影響。

1、Kubernetes 並不能明顯的減少微服務所需開銷

當開始編寫一個新微服務時,第一步就是導入大量的代碼,將其分佈在數百個不同的包中。安裝一個極簡的 Node.js 微服務框架時,ExpressJS 會獲取到 100 個依賴項。在能用該框架寫出 “Hello World” 之前,這些依賴項就是 100 個上游庫。這些依賴關係,在開始編碼之前,代碼的最低起點是 54,000 行,這還是對於最小化的框架而言。如果在向其中加入類似 Locomotive 這樣的 MVC 層,起始代碼的數量就會躍遷至近 22 萬行。這種情況並非是當你使用 JavaScript 或 Node.js 時纔會發生,類似的情況在大多數編程語言中比比皆是。

在此基礎上,在將 “業務邏輯” 分層在框架之上。與起始階段的幾萬甚至幾十萬行代碼相比,業務邏輯那僅僅幾千行的代碼,通常只是依賴關係上的一層皮毛。

爲了運行一個微服務,需要從一個 HTTP 服務器開始。這個服務器上將只運行一個微服務,並且需要一直運行。因此再生產中,需要擴展到多個實例,以便能夠有效的處理故障情況和負載高峯。

而代碼行數的多少部分決定了需要什麼樣的計算資源。代碼庫越大,內存和存儲就會越多,最終導致使用的 CPU 也越多。在現如今的雲計算世界裏,這就直接轉化爲需要的計算單元的大小。然後,考慮到每個計算實例的基本需求,在將其乘以需要運行的副本數量。最後在考慮到一般應用的微服務的平均流量,可以得出要支付的成本是以複製的方式保持一個完整的應用一直在運行,即使它在大部分時間都處於空閒狀態。

這些都是傳統微服務需要支付的開銷。雖然 Kubernetes 幫助解決了運行時存在的問題。它的存在讓不需要在每個虛擬機上運行一個微服務,而是運行一些龐大的虛擬機,讓 Kubernetes 把負載分配給它們。但是需要支付的開銷依然並沒有減少。Kubernetes 也從未表明它的核心價值是降低雲計算成本。現在的情況是,就算使用 Kubernetes 運行微服務,依舊要擁有足夠的計算能力,來保持這些微服務一直運行,無論它們是否收到請求。

如果對經濟性感興趣,如果對在生產中運行時省錢感興趣,即使只是對消耗更少的 CPU 和內存感興趣,那麼現在也是時候挑戰每個微服務都以數十萬行的導入代碼開始的想法了。

但在理解這意味着什麼之前,可以從安全的角度來談論它,儘管也可以從開發者壓力的角度來談論它。

2、安全可以更容易

在微服務開始時有 50 至 100 個依賴關係,其中許多依賴關係都是跨領域的。這意味着並不直接使用它們,它們是其他依賴關係的依賴。在你寫下第一行代碼開始,就需要做好承擔安全責任的準備。因爲每當這些庫中的一個漏洞被暴露出來,或者發生了零日漏洞在上游庫被修復的情況時,開發者這些在依賴關係上編寫應用程序的人就是那個修復或採取防禦措施的人。

在傳統的微服務架構中,作爲開發者要對安全操作的方面負責。而現在,只要從其他來源導入代碼,安全操作這個問題就會存在。雖然通過使用其他庫,會獲得很多好處。但在某種意義上,必須接受這樣一個事實:操作性問題的依賴關係安全性,將永遠成爲開發者的關注點,因爲開發者是必須解決這個問題的人。

但可以在堆棧的最關鍵層減少風險。在目前的微服務架構中。代碼包括 HTTP 服務器、TLS 實現、主機運行時代碼、系統接口和其他低層次的問題。除此之外,由於開發者的代碼是作爲主機操作系統上的一個進程運行的,所以開發人員也就要承擔起進程安全的責任。還是以一種非常現實的方式,畢竟當安全問題出現時,進程是整個模型中最敏感的部分。

換句話說,突破進程、劫持 SSL 或訪問系統文件往往會出現最嚴重的安全缺陷。而在目前的微服務模型中,開發人員一般依靠外部庫來處理這些問題,並將這些庫複製到自己的代碼庫中,然後開發者負責在出現漏洞時做出反應。一般開發者對堆棧中最關進的部分都會採取這種做法。但開發者需要對堆棧這部分負責嗎?目前還不清楚開發者是否真的需要負責。

3、做好微服務的更好方法

微服務已經做的很不錯了。把複雜的工作流程分解成更容易管理的小塊,也正確地考慮了關注點的分離。準確來說,開發人員把任何特定單元的認識開銷保持在相對較低的水平。反過來,開發者也得到了很好的服務。

相比之下,上面看到的問題是低層次的問題,它們的出現與開發人員做出的技術選擇相關,而且開發人員一般在很大程度上忽略了這些問題。不過,可以從亞馬遜的 Lambda 的功能即服務 (FaaS) 模型中找到一些替代方案來避免這些問題。FaaS 承諾,開發人員可以不用編寫出一整個服務器,而是隻寫一個處理函數就夠。當收到輸入指令時,該函數將被執行,並且只運行到它能產生輸出就會被送回。這種模式就很令人舒服,因爲幾乎沒有 “低級” 代碼需要管理。

當然,FaaS 並不是萬能的,它也存在問題,首先,FaaS 的實現是被平臺約束的。亞馬遜的 FaaS 和 Azure 的工作方式不同,就導致你使用了 FaaS 就無法使用 Azure。第二,因爲平臺施加了限制,所以 FaaS 能做的事情是有限的。不一定需要深入研究這些細節,僅從表面上看,由於 FaaS 的這些限制,導致它與微服務相比,使用限制相當明顯。

但如果把 FaaS 的強項移植到微服務模型上會怎樣?能夠爲微服務架構建立一個更好的基礎?如果看一下現在流行的網絡框架,會發現頂層模式是相當標準的將路由映射到處理函數中。在大多數情況下,底層代碼沒有什麼是真正需要開發者關注的。可能需要你去配置一些東西,比如主機名或端口號什麼的。但很少有人會從一個框架開始就花時間去修補 HTTP 或 TLS 的實現。因爲從這開始,就會爲程序增加人外的代碼數量。因此,下一代微服務平臺的邏輯位置就是消除基本的依賴關係,讓其工作時僅運行 HTTP 服務器。TLS、流程管理和基本路由。

編寫一個新的應用程序將從映射路由到處理函數開始,而不是通過創建一個 Web 服務器。理想情況下,這就是應用程序的安全邊界運行的地方。開發人員將對代碼和任何新依賴關係的安全負責。但該平臺將保持較低的水平,使其升級成爲一個操作性問題,而不是開發者的問題。最重要的是,這意味着一個 SSL 補丁(例如)將不需要你重建、重新測試和重新發布你的應用程序。相反,你只需要更新你的主機運行環境,這通常可以在沒有任何開發人員參與的情況下完成。

像 FaaS 模型一樣,以這種方式編寫的代碼可以 "擴展爲零"。這也就意味着,當你的代碼沒有處理請求時,它就不會運行。底層平臺將一直在那裏等待新的 HTTP 請求。但由於請求處理方法的安全邊界存在,導致多個應用程序可以使用同一個 HTTP 監聽器,反過來看,意味着可以實現更高的密度。而在這種情況下,這直接轉化爲計算需求。

不過,也需要做一些架構上的思考。因爲在這種模式裏,應用程序的啓動速度成了一個關鍵。需要的啓動速度要低至微妙甚至是毫秒的程度,而基於容器的服務啓動速度一般都傾向於 15-120 秒。雖然很多人都對 “無狀態微服務” 口誅筆伐,但現在它是一個真正需要達到的要求。

4、我們有 WebAssembly!

容器生態系統以及之前的虛擬機生態系統的只要好處是隔離。虛擬機提供了一個隔離工作負載的有效方式。而容器的出現再次完善了它。上面談論的從本質上消除 Web 服務器來減少微服務的代碼數量是一個非常好的想法。

但又出現了一個新問題,還能實現所期待的隔離水平嗎?對於這個問題可以毫不猶豫的回答:當然可以,因爲我們有 WebAssembly。

WebAssembly 最初被認爲是一個瀏覽器執行環境,是超越 JavaScript 的一步,是做 Java Applets 和 ActiveX 曾經試圖做的事情的更好方法。但事實證明,在目前的情況下,瀏覽器的沙盒模型正是需要的沙盒模型。雖然它在運行時不信任(或沙盒)二進制文件,但通過能力模型,它確實會有選擇地給沙盒中的代碼提供功能。而其中啓動速度是最重要的,畢竟用戶不喜歡緩慢的網站。另外,主機的架構和操作系統不必與開發者的主機和操作系統相同,這也是雲計算的一個優勢。此外,WebAssembly 格式被設計爲許多編程語言的編譯目標。

WebAssembly 所具備的能力正是微服務的新迭代所需要的。開發人員可以用任何想要的語言,例如 Rust、C、JavaScript、Python 等等,去編寫 HTTP 處理程序,然後將其編譯爲 WebAssembly。這樣當主機運行時就會提供必要的功能,如文件系統(高度沙盒化的)、出站 HTTP、鍵 / 值存儲等。可以把微服務集中在處理離散的問題上。而底層平臺可以用來管理所有的 HTTP、SSL/TLS 等等。

Fermyon 就正在研究一個這樣的平臺,它與一組可插拔的組件相結合,將安全地提供微服務所以需要的能力。而在這個過程中他們還發現了這種工作方式的一些額外的優勢。

5、工具標準化

當網絡服務器被外部化,或將組件作爲能力注入到運行當中時,開發人員對代碼進行檢測就會獲得一些好處。這些好處表現爲對運行代碼的調試、診斷和監控方面的改進。

例如,可以通過提供標準化的指標和入職作爲開始。將其植入到平臺中去。因爲每個請求的計時都是隨時可以使用的,所以不需要浪費時間開發,還有正常運行時間、可用性和故障報告也是一樣的道理。所有的這些都是平臺自帶的功能,因此不需要開發。

還有更令人開心的事,當你開始在應用程序中記錄日誌時,平臺可以將日誌信息轉化爲日誌分析器喜歡的結構化格式。而這些信息與更廣泛的平臺日誌緊密的聯繫在一起。這也就意味着,開發者過去需要做的無聊的雜事之一,現在可以交給平臺來處理了。而且可以更輕鬆的做日誌分析並獲得豐富的指標。

當然還可以讓做到眼不見,心不煩,平臺可以將指標和日誌組件帶入 WebAssembly 二進制文件中。在這種情況下,開發人員能夠輕鬆的利用模塊中的函數調用來插入指標數據,並將這些信息直接發送到平臺的指標工具中。這不能讓這項工作更簡單,僅僅是讓其變得不可見了而已。

6、實現細節和數據服務的外部化

有時開人員關心自己的鍵 / 值是否 Redis,有時卻又漠不關心。Fermyon 平臺確保了對鍵 / 值存儲、對象存儲、文件系統、環境變量等功能,只提供一個實現。本地文件只能使用平面文件。服務器版本可以使用 Redis、Minio 和 NFS。雲版本可以使用託管版本。但是對於開發者來說,API 是一樣的。調用一個函數來指定一個鍵和值,調用另一個函數來傳遞鍵和值。其實只要核心功能按照預期工作,實現細節就無關緊要。

WebAssembly 組件模型使數據服務外部化成爲一種可能,而且不需要特殊的中間件層或外部服務。相反,在啓動時,WebAssembly 運行環境會自動選擇正確的組件來滿足開發者指定的界面要求。面向對象的開發者可能會從接口 / 類的角度考慮這個問題,但有一個關鍵區別,選擇實現一個接口是運行時一個操作,而不是開發者代碼的一部分。

這個由 WebAssembly 帶來的可能性有助於對微服務進一步的理解,幫助開發人員重新思考對分佈式計算的理解。

7、將分佈式計算推進一步

曾經的分佈式計算在實踐時顯得非常混亂。單片機應用在這方面展現出笨拙的一面。但現在這一切都發生了變化。容器成爲了一種新興事物,Go 語言等在很大程度上借鑑了 CSP 等分佈式計算概念。更重要的是,微服務架構的出現挑戰了分佈式計算很難,以及對它應該如何完成這兩個假設。

時代發展,舊的教條退去了。開發人員開始把分佈式計算看做事一個新問題,而關於這個問題可以通過小型和狹義的網絡服務、REST-ful 應用程序以及對無狀態計算的投入組合來解決。Kubernetes 爲部署微服務架構提供了一個強調無狀態方式的協調框架。

分佈式計算似乎並不是一個很難實現的目標。但開發人員需要做出的架構決策卻被推到了風口浪尖上。因此,我覺得需要認真的思考下微服務應該如何實現結構化,以實現正確的網絡拓撲結構。有意思的是,當 Go 將 CSP 融入自身時,Kubernetes 也將 CSP 融入了基礎設施中。而開發者不得不在兩個不同的抽象層次上思考同一個模式。

而 WebAssembly 是爲開發人員提供的另一種實現分佈式計算的方法,它可以減少開發分佈式應用的認知開銷。而組件模型正是實現這一目標的關鍵。在上面,我們把組件看成是將外部服務嫁接到微服務的一種方式。但並沒有真正的談及組件是什麼這個問題。因爲其中很重要的一點是,接口的定義使得實際的實現細節和開發者無關。而且其中一些實現實際上是底層主機運行時帶來的功能。這些功能在運行時被掛到了 WebAssembly 二進制文件中。

但是一些其他的實現卻不是主機運行時的一部分。它們只是其他的 WebAssembly 模塊,在啓動時被鏈接到了一起。這樣一來,它們對開發者來說就像是一個庫。但在平臺上卻是作爲一個獨立的 WebAssembly 模塊被執行。它們有自己的內存空間,並與開發者的代碼相互隔離。當開發者與這個外部組件交互時,感覺起來像是調用了一個函數,但行爲上看起來更像一個 RPC。

這也正是分佈式計算有趣的地方,在運行時,不是開發者在處理計算的分佈。就開發者而言,它只一個對庫的調用。運行時可以選擇在哪裏運行該組件,且與開發者的代碼相鄰。開發者對它唯一關心的就是功能是否被正確的、安全的、可靠的執行,僅此而已。分佈式計算不再是第一代微服務的複雜拓撲結構,它是編寫微服務新方法中的一個事實細節。

8、結論

微服務架構一直是以云爲中心開發的主要推動力,這一點是毋庸置疑的。而虛擬機開啓了微服務架構的可能性。在微服務的第二波浪潮中,容器生態系統將分佈式計算與微服務編撰爲雲計算的 “新常態”。而在這一過程中,遇到了一些困難。這使得我們暫停下來並重新思考一些假設,關於安全、關於設計、關於與外部服務合作的假設。

當我們思考這些假設時,看到了 WebAssembly 帶來的可能性。我們可以以此來減少開發人員在關鍵層面安全上花費的時間。而且還減少了微服務開發者必須撐到的代碼數量。與此同時,還可以改善日誌和指標,同時簡化管路外部服務的過程。而提供這些優勢機制——WebAssembly 組件模型,爲我們提供了一個光明的分佈式計算未來版本。

參考鏈接:https://www.fermyon.com/blog/rethinking-microservices

歡迎關注「幽鬼」,像她一樣做團隊的核心。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/bwo2sDA8u3ArZ58P03ReKQ