Serverless 下的微服務實踐

作者 | 弈川 

本文整理自《ServerlessLive 直播課》,關注 Serverless 公衆號,回覆 “927”,即可獲取本堂課程 PPT!

微服務架構介紹

微服務架構誕生背景

在互聯網早期即 Web 1.0 的時代,當時流行的是單體應用,研發團隊比較小,主要是外部網頁,然後新聞門戶等;到了新世紀的互聯網時期 Web 2.0 時代,網民數量大幅激增,相繼出現電商、社交這樣巨無霸級別的互聯網產品,出現了幾百人甚至上千的研發團隊在一個場景下,流量及業務複雜度相較於上一個時代有了質的變化,因此單體服務的弊端:例如研發效率等問題便顯現出來。

此時出現了一個叫 SOA 的架構,其架構思路與微服務很像,它有類似於 ESB 這種中心化組件,阿里的 HSF,包括後來開源的 Double,都是在此階段誕生的。

移動互聯網時代出現之後,各種各樣的 APP 誕生,生活也開始全面互聯網化。大流量高併發以及規模化的研發團隊變得越來越尋常,相應對高技術、生產力的要求也在逐步提升,此時微服務的概念應運而生。

微服務其實一直貫穿在整個架構的發展過程中。在 Java 的技術棧,類似於 Spring Cloud 、Double 這些框架都已經非常流行。不難發現整個社會已經步入數字化高速發展階段,此時更大的問題蘊含其中,如流量升高、應用複雜度提升,研發團隊擴大、對於效率的要求增高等等。

單體時期 1.0 版本

大部分的公司或早期業務都會經歷過這樣的過程(如圖所示):先是客戶端,此時需要通過一個入口訪問,上圖中 SLB 是阿里雲一個負載均衡服務,它相當於一個網絡入口,可以對應到 ECS(ECS 爲阿里雲的虛擬機)打到對應的單體的服務中,而此時他們會共用一個數據庫,這是第一個時期。

單體時期 2.0 版本

到第二個時期 SOA 架構:此時出現了分治的思想,它會將一些業務進行拆分。但它並未做到服務與底層的拆分,如存儲數據庫的拆分,其本質上還是共用一套數據庫,因此它還是單體的架構。

微服務時期

而到微服務時期,如若客戶端通過 SLB 訪問網關(如圖所示),隨後會轉發對應的服務,且服務與服務之間會產生一些調用;每個服務會對應一個單獨的數據庫或緩存,且每個服務會通過類似於 Nacos 這種的服務進行註冊、發現以及配置管理。

微服務引入之後,雖然解決了架構業務的分離,能夠讓研發團隊在某一個領域、業務能夠做到精專,不過從整體架構來看便會發現,相較於之前它其實是更爲複雜的,所以也帶來一些運維上的問題。

在單體架構中於單體應用而言,會發生邊界不清晰、模塊耦合、共享代碼庫容易衝突的問題,同時如果團隊規模較大,此時的協作效率也會相對較低。但是微服務架構的核心就是解耦,如果做到拆分之後的解耦,就可以釋放開發團隊效率。

雲原生時代微服務架構發展

微服務技術在雲原生時代的技術引進

雲原生是一個很宏觀的概念,如果我們以微服務爲起點來看雲原生給微服務帶來的變化與演進,可以更好地幫助我們理解什麼是雲原生。

微服務和單體應用的本質是什麼呢?(如圖所示)它其實是把單體應用從一個巨型的應用拆分成數個微小的服務,協作來完成原先單體應用等效的業務服務。此時微服務與微服務之間會形成一個依賴關係,它需要部署至一個或多個資源上,這時的資源便是計算資源。

過去單體應用與資源之間的關係十分簡單,單體應用的協同也都是一些內部協同,不存在外部動態的依賴。但架構轉換到微服務之後,由於外部依賴和節點數量的爆炸,整個體系會變成網狀,管理起來十分複雜。超過 50% 的企業會覺得采用微服務架構,最大挑戰是複雜的運維,即整個服務生命週期的管理。

如今,比較公認的一點是雲原生的根基在於容器與容器的管理編排(K8S)。而容器與 K8S 的技術能夠幫助我們解決微服務體系中所存在繁雜運維的問題。

首先不同的微服務之間會存在異構,即一個團隊,在微服務體系下爲了發揮最大效能,可能會允許不同小團隊採用不同的編程語言、運行環境去運行微服務。因此最初我們在運維和管理微服務時,是沒有統一的標準去處理這些異構環境的。這便促發了雲原生容器技術的流行,因爲這項技術的作用就是通過一層標準化的運行時和封裝來限制微服務部署。這樣從生命週期與管理角度來看,每一個微服務之間的差異變少,十分有利於資源的調度。

隨後。基於容器調度衍生出了容器平臺。容器平臺就是管理容器的,就 K8S 來說,它可以標準便捷地將微服務運行到底層的資源上,隨後存儲計算網絡可以通過 K8S 這層來進行統一封裝,一層抽象與封裝,它類似於雲原生時代的操作系統。

它具體會提供哪些幫助呢?在 K8S 中有個概念叫 POD ,POD 是一組容器的結合,與微服務實體生命週期的耦合,在一個 POD 裏面,它可以運行一個或者是多個容器。

採用微服務架構時,一般會把微服務運行的主體放在主容器中,也就是把微服務執行的主邏輯放在主容器裏面。此時主容器的生命週期與 POD 的生命週期是完全耦合的,POD 什麼時候消亡,微服的運行主體便何時消亡。除此之外我們還會運行一些邊車容器— Sidecar,它主要是爲主容器提供輔助功能,如日誌採集、網絡代理、身份鑑權等 。此時的微服務便除了提供自身核心業務以外,它還可以動態的提供額外輔助能力,這讓微服務的管理變得更加穩定與便捷。

POD 這個模型還提供了許多非常有用的功能,比如狀態信息。(狀態信息是指:POD 會提供一個標準的接口來顯示運行時的狀態)通過這個信息狀態可以出判斷微服務或是容器的運行狀態,如它是否處於運行中、業務是否已經準備好可以迎接流量接入,POD 爲整體的穩定性提供了保障。另一個是地址服務功能,每個 POD 會有一個標準化的 DNS 地址服務,它對於需要統一暴露出來的 API ,日誌監控追蹤能力都十分有幫助。通過 DNS 的日誌地址來訪問以及暴露的可觀測性信息,可以快速發現運行時的問題。由此便可總結:容器及容器平臺能夠在微觀上幫微服務具備更多的能力。

圖中爲 4 種發佈模型:

  1. 滾動更新

  2. 固定更新

  3. 藍綠部署

  4. 金絲雀發佈(灰度發佈)

流量治理

微服務將過去單體時期靜態的通信關係,通過拆分編成動態運行時。通常服務間的通信與協同是需要單獨管理的,微服務框架幫助我們進行了每個服務通用功能的抽象與實現。

抽象層面包含兩方面:業務邏輯與通信、流量、服務治理能力。我們可以將底層通用能力抽象成一個具體的框架,但是不同微服務之間的框架是沒辦法實現相互調用的。而到了雲原生時代,它能夠使用不同的開發語言以及模型進行編程,實現微服務的研發。

Service Mesh 服務網格就是爲了解決流量治理在多語言,多環境下的問題而出現的。

在數據層面,Sidecar 負責流量劫持轉發以及管理,該功能典型 Sidecar 實現就是 Envoy。

如圖它會先將上面部分從框架層面抽象出來後與業務直接進行解耦,將通用能力放在 Sidecar 中,通過 Sidecar 之間的通信、轉發去管理;這樣會使問題變得簡單很多。開發者只需要在流量管理和 Sidecar 之間通信,不同技術棧的微服務實例便可實現互相通信。

除了數據層面,我們還需要管控層面的支持。需要一個組件來實現原微服務體系中的策略規則的管理,經典實現就是 Istio。比如在原來在微服務體系中的服務註冊、服務發現、流量觀測等能力是需要管控層面的主線去完成的。有這些能力之後它就組成了 Service Mesh。我們可以通過管理 POD 中的流量以及數據層面的單點,讓他們形成網狀結構,變成集羣實現流量的分配、安全、觀測。

圖中的編程模型與函數計算相關

請求驅動是基於請求的動態彈性伸縮,並簡化請求處理的邏輯。微服務的調用,從流量進來後,會經過 4 層或者 7 層的負載均衡分發到不同的微服務實例;但是在同一個微服務實例進程的內部,一般會有兩個邏輯:第一個是請求管理,它可能是一個 HTTP 服務器,或者是一些 Handler,也可能是一些隊列管理,請求分發能力的組成;這些組成最終會將請求提交到第二部分,即請求處理中,而請求處理也是開發者真正需要實現的一些邏輯。

比如說 Java Go 、Python,它們都有自己的一套請求管理邏輯,請求管理和請求處理之間會形成強烈的耦合,這個實例既包含請求的管理,又包含請求處理的邏輯。在這個架構下不存在一個全局獨立,且可以感知到請求去進行流量管理的控制層,只有到整個實例自身的處理層才如此解釋請求。即便此時微服務實例已然過載,也很難再次將這個請求轉發到其它微服務實例上進行負載均衡。因此請求驅動系統就是查數據、並解決這兩個要素,開發者實際在做的就是請求驅動的解耦。

如圖所示,首先外部系統傳輸過來的請求會先進行標準化,有一個適配器;標準化之後就會將其放在請求負載均衡器中,這個負載均衡器可以理解該請求本身的語義;然後它可以驅動並進行處理。當處理單元不夠時,它可以通過管理器來進行擴容;邏輯單元比較多時,它還可以進行縮容,這樣便形成了一個動態管理,可以爲開發者節約非常多的成本。

請求驅動模型:

  1. 請求標準化

  2. 請求路由

  3. 處理管理

將請求標準化、請求路由、處理管理等組合起來,便與 Serverless 的概念吻合。開發者根本不需要去關心 Server ,只需要去專注業務邏輯即可。這其實也是微服務體系與平臺化的 Serverless 架構融合的過程。阿里雲的 FC (函數計算)和 SAE(應用引擎) 都是以解決這些問題爲核心的。

微服務 + Serverless 的最佳實踐

Serverless 其實經過了很多年的發展,其理念最早可以追溯到 2012 年;2014 年 AWS 正式推出 Lambda,才掀起了 Serverless 浪潮;但隨後而來的是一段沉靜的發展期。這種情況出現的原因是爲什麼呢?分析來看是因爲函數計算的開發模式與原本模式有非常大的出入,它更適合前端而不是 long running 形式的一些應用,它更偏向基於請求的一些處理。因此那些需要長時間運行的服務或應用架構便不太能夠享受到 Serverless 所帶來的彈性和降本提效等紅利。

微服務架構的痛點

微服務的痛點在於穩定性。微服務帶來了許多其他組件。例如服務發現、或是其他的一些工具類的產品,這些在單體情況下會變得更加複雜,因爲整個架構變成網狀結構。容器與容器平臺在某些程度上是幫助我們承載微服務這部分的運維的,但是其本身如容器 K8S 都是存在一定複雜性的。

K8S 的架構圖

K8S 不僅複雜也存在一些痛點:

  1. 容器鏡像部署方式差異

  2. K8S 組件運維的複雜

  3. 學習成本

對於開發者來說是最有吸引力的是不需要改變原本的開發方式的基礎上可以將精力專注於業務邏輯。而微服務比較理想的狀態也是開發者只需關注架構中的業務系統,其它部分如:網關 CICD 發佈系統、驗貨流程,註冊中心、告警監控、分析日誌,這些通通都不再需開發者再去關心。其優勢可以總結爲:

  1. 讓開發者專注業務邏輯

  2. 不改變原有開發方式

  3. 無需關心與運維底層資源

  4. 具備彈性能力可以降低閒時成本

  5. 優秀的工具鏈

總結

微服務體系在整個雲計算發展的時代有不同的事件。如最開始部署就是傳統的 IT 設施,像 IDC 這種機房,微服務提供的是靜態的物理計算資源。

然後到了第二步就是雲託管時代,就是我們大家所熟知的 VM,阿里的話就是 ECS ,它可以提供彈性的計算資源,但它並沒有實質的改變,只是資源上變成彈性,它對於服務、微服務的部署,包括管理運維等本質上都沒有太大變化。

到了第三階段雲原生時代,雲平臺、雲服務都可以承擔這些複雜的運維操作、配置、管理。微服務提供的就是一個運行環境與平臺,此時用戶只需要去關心業務系統、以及如何實現業務系統即可。將複雜的技術變得越來越簡單,讓用戶不再感知那些煩雜的操作,由平臺代替用戶去做重複的、難以維護的工作,這也十分符合計算機技術整體的發展方向。

參考閱讀:《雲原生時代,微服務如何演進?》

https://developer.aliyun.com/article/771128

弈川

阿里云云原生團隊

目前從事阿里雲 Serverless 應用引擎的研發工作,專注於 aPaas、微服務、分佈式系統、Serverless 工具鏈等方向,致力於打造下一代 Serverless 平臺,讓傳統應用的開發者能零改造、低成本的享受 Serverless、K8S 等技術紅利。

社區官網

http://www.serverless-devs.com/

項目倉庫

https://github.com/Serverless-Devs/Serverless-Devs

Serverless Desktop 桌面客戶端

https://serverlessdevs.resume.net.cn/zh-cn/desktop/index.html

Serverless 應用開發者套件

http://serverless-dk.oss.devsapp.net/docs/tutorial-dk/intro/react

Serverless Devs CLI 

https://serverlessdevs.resume.net.cn/zh-cn/cli/index.html

Serverless Hub 應用中心

https://serverlesshub.resume.net.cn/#/hubs/special-view

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