後Kubernetes時代的微服務
本文要點
- 當前微服務架構依然是最流行的分散式系統架構風格。Kubernetes和雲原生運動已大規模地重新定義了應用設計和開發中的一些方面。
- 在雲原生平臺上,服務僅具備可觀測性是不夠的。更基本的先決條件是使用檢查健康、響應訊號、宣告資源消耗等手段實現微服務的自動化。
- 在後Kubernetes時代,服務網格(Service Mesh)技術已完全取代了使用軟體庫實現網路運維(例如Hystrix斷路器)的方式。
- 當前,設計應針對“可恢復性”。為此,微服務需要實現多個維度上的冪等性。
- 現代開發人員必須做到不僅要精通程式語言去實現業務功能,而且同樣也要精通雲原生技術去滿足一些非功能性基礎架構層上的需求。
微服務的關注熱度起源於一大堆極端的想法,涉及組織的結構、團隊的規模、服務的規模、重寫和丟擲服務而不是修復、避免單元測試等。依我的經驗看,其中大部分想法已被證明是錯誤的、不實用的,或者至少在一般情況下是不適用的。當前能殘存下來的微服務原則和實踐,大部分是非常通用和寬鬆定義的。雖然它們適合未來許多年內的發展,但在實踐中並沒有多大的意義。
早在Kubernetes橫空出世的幾年前,微服務理念就得到了採用,目前,它仍然是一種最流行的分散式系統架構風格。Kubernetes和雲原生運動已大規模地重定義了應用設計和開發的一些方面。在本文中,我試圖提出一些原始的微服務理念。我將指出,這些理念在後Kubernetes時代已不再像以前那樣強大。
服務不僅應可觀測,而且應是自動化的
可觀測性(Observability) 是微服務自一開始就提出的一個基本原則。可觀測性雖然適用於一般的分散式系統,但是當前,尤其是在Kubernetes上,可觀測性的主要涉及平臺層的開箱即可用,例如程序執行狀況檢查、CPU和記憶體消耗等。應用能以JSON格式登入控制檯,這就是可觀測性的最低要求。此外,平臺應可以在無需過多服務層開發的情況下,實現跟蹤資源的消耗、開展請求追蹤、收集全部型別的指標、計算錯誤率等。
在雲原生平臺上,服務僅具備可觀測性是不夠的。更基本的先決條件是使用檢查健康、響應訊號、宣告資源消耗等手段實現微服務的自動化 。任何應用都可以置於容器中並執行。但是要建立一個可通過雲原生平臺自動化和協調編排容器的應用,則需要遵循一定的規則。遵循這些原則和模式 ,可確保所生成的容器作為雲本地成員在大多數容器編排引擎中表現為優秀,並支援對容器進行自動化的排程、擴充套件和監視。
我們希望平臺不僅可觀測服務中發生的情況,而且希望平臺能檢測到異常,並按照宣告情況做出協調。糾正措施可以是通過停止引導流量到服務例項、重新啟動、向上/向下擴充套件,也可以是將服務遷移到另一臺健康的主機、重試失敗的請求或是其它一些操作。如果服務實現了自動化,那麼所有這些糾正措施都會自動做出,我們只需要描述所需的狀態,而不是去觀測並做出響應。服務應該是可觀測的,但也應在無需人工干預的情況下由平臺實現問題整改。
具備正確職責的智慧平臺和智慧裝置
在從SOA轉向微服務的過程中,在服務互動上發生的另一個根本轉變就是“智慧端點啞管道”(smart endpoints and dumb pipes)這一理念 。在微服務領域,服務不依賴於所具有的集中式智慧路由層,而是依賴於具有某些平臺級功能的智慧端點。服務的實現是通過在每個微服務中嵌入傳統ESB的部分功能,並轉為使用不具有業務邏輯元素的一些輕量級協議。
這仍然是一種慣常採用的方法,即在不可靠的網路層(使用諸如Netflix/Hystrix" rel="nofollow,noindex" target="_blank">Hystrix 之類的庫)實現服務互動,但在當前的後Kubernetes時代,服務互動已完全被服務網格(Sevice Mesh 技術取代。服務網格吸引人之處在於,它甚至要比傳統的ESB更智慧。網格可以執行動態路由、服務發現、基於延遲的負載平衡、響應型別、指標和分散式跟蹤、重試、超時,以及我們所能想到的所有特性。
與ESB的不同,服務網格只有一個集中路由層,每個微服務通常都具有自己的路由器,即一個使用額外中央管理層執行代理邏輯的“跨鬥模式容器”(Sidecar Container)。更重要的是,管道(即平臺和服務網格)中並不維持任何業務邏輯。管道完全聚焦於基礎架構問題,而讓服務聚焦於業務邏輯。下圖表示了為適應雲環境的動態和不可靠特性,ESB和微服務在認知上的演變情況。
圖從SOA到MSA和CNA
如果檢視服務的其他一些方面,我們就會注意到雲原生不僅影響了端點和服務互動。Kubernetes平臺(及其所有附加技術)還負責資源的管理、排程、部署、配置管理、擴充套件和服務互動等。與其再次稱之為“智慧代理啞管道”,我認為更好的描述應是一種具備正確職責的智慧平臺和智慧服務。它不僅是與端點相關,而且也是一個完整的平臺,實現主要聚焦於業務功能的服務在所有基礎架構上的自動化。
設計不應針對“故障”,而應針對“恢復”
毫無疑問,要在基礎架構和網路本身並非可靠的雲原生環境中執行微服務,我們必須針對故障做出設計。但是越來越多的故障是由平臺檢測並處理的,而人們對如何從微服務中捕獲故障的考慮較少。相反,我們應通過考慮從多個維度實現冪等性,設計我們的恢復服務。
容器技術、容器編排和服務網格(serive mesh)可以檢測許多故障,並從中進行恢復。例如無限迴圈(分配CPU份額)、記憶體洩漏和OOM(執行狀況檢查)、磁碟佔用(配額問題)、Fork炸彈(程序限制),批量處理和程序隔離(限制記憶體份額)、延遲和基於響應的服務發現、重試、超時、自動擴充套件等。同樣,在過渡到無伺服器模型後,服務必須在幾毫秒內處理一個請求。看上去對垃圾回收、執行緒池、資源洩漏等問題的關注,越來越成為一些毫不相關的問題……
使用平臺處理所有諸如此類的問題,會將服務視為一個密封黑盒子。該黑盒子應支援多次啟動和停止(支援服務重新啟動)、服務按比例的放大和縮小(通過將服務成為無狀態的以支援安全擴充套件)、假定許多傳入請求最終會超時(使端點具有冪等性)、假定許多傳出請求將暫時失敗並且平臺將會做出重試(確保我們使用了冪等服務)。
為實現自動化在雲原生環境中適用自動化,服務必須滿足下列條件:
- 對重啟的冪等(服務支援多次被殺掉並啟動)。
- 對向上/向下擴充套件冪等(服務可實現多個例項的自動擴充套件)。
- 對服務生成者冪等(其它服務可重試呼叫)。
- 對服務消費者冪等(服務或服務網格可以重試傳出請求)。
如果服務在一次或是多次執行上述行為中總是表現出同一方式,那麼平臺就可以在無需人工干預的情況下從故障中恢復服務。
最後請記住,平臺提供的所有恢復只是一些本地優化。正如Christian Posta所指出的 ,分散式系統中應用的安全性和正確性仍然是應用的責任。對於設計一個整體穩定的系統,業務流程整體範圍中的思維模式(可能跨越多個服務)十分重要的。
雙重開發職責
越來越多的微服務原則已被Kubernetes及一些補充專案實施和提供。因此,現代開發人員必須做到不僅要精通程式語言去實現業務功能,而且同樣也要精通雲原生技術去完全滿足一些非功能性基礎架構層上的需求。
業務需求和基礎架構(操作上的需求、跨功能的需求,或是一些系統質量屬性)之間的界限通常是模糊不清的,我們不可能只採取其中的某個方面,而期望其他人去實現另一個方面。例如,如果要在服務網格層實現重試邏輯,那麼必須使服務中的業務邏輯或資料庫層所使用的服務具有冪等性。如果在服務網格層使用超時,那麼必須在服務中實現服務使用者超時的同步。如果必須要實現服務的定期執行,那麼必須配置Kubernetes作業去按時間執行。
展望未來,一些服務功能應作為業務邏輯實現在服務中,而其它一些服務功能則應作為平臺功能提供。雖然使用正確的工具去完成正確的任務是一種很好的責任分離,但新技術不斷出現極大地增加了整體的複雜性。要在業務邏輯方面實現簡單的服務,我們需要很好地理解分散式技術堆疊,因為開發職責是分散在各個層上的。
事實證明,Kubernetes支援向上擴充套件到數千個節點,數萬個Pod和每秒數百萬事務。但它是否同樣支援向下擴充套件?對我來說,我並不清楚應用的規模、複雜性或關鍵性的閾值應該是多少,才能證明我們引入複雜的“雲原生”是正確的。
結論
看到微服務運動為採用Docker和Kubernetes等容器技術提供瞭如此巨大的動力,這是非常有意思的。雖然在一開始是微服務實踐推動了這些技術的發展,但現在是Kubernetes重新定義了微服務架構的原則和實踐。
從最近的一些例項看,我們將很快採納功能模型作為有效的微服務原語,而不是將微服務視為奈米(nanoservice)服務的反模式。我們並沒有充分質疑雲原生技術對於中小型案例的實用性和適用性,而是出於興奮有些隨意地投身到這個領域中。
Kubernetes從ESB和微服務中汲取了大量經驗,因此它將會成為最終的分散式系統平臺。它是一種用於定義建築風格的技術,而不是反之。究竟是好是壞,只有時間才能證明。
作者簡介
Bilgin Ibryam(@bibryam) 是Red Hat的首席架構師、提交者和ASF成員。他也是一名開源佈道師、部落格作者,《Camel設計模式》(Camel Design Patterns)和《Kubernetes模式》(Kubernetes Patterns)等書的作者在他的日常工作中,Bilgin 喜歡指導、編碼和領導開發人員成功地構建雲解決方案。他目前的工作重點是應用程式整合、分散式系統、訊息傳遞、微服務、DevOps 和雲原生的挑戰。可通過Twitter
、Linkedin
和個人部落格
聯絡Bilgin。