天天看點

雲原生時代,微服務如何演進?

雲原生時代,微服務如何演進?

一 微服務架構與雲原生

微服務從 2010 年左右開始興起。最開始大家會把微服務架構應用在傳統 IT 的基礎設施,也就是傳統的 IDC 或者說實體機上,我們使用這些實體機為我們的微服務架構提供資源,形成一個分布式的系統,互相協作、協同。

随着我們整個的 IT 基礎設施的發展,逐漸到了雲的時代。

雲原生時代,微服務如何演進?

我們在雲時代做的第一步是雲托管,也就是把在傳統 IDC 之中的實體機,換成雲上的虛拟機以及雲上虛拟的彈性資源,對于微服務架構其實改動并不是非常巨大。我們把原來部署在實體機上的架構模型,可以比較容易地轉到在雲上托管的虛拟機中,也稱之為 Lift and Shift 方式。與此同時,在雲托管時代,我們也嘗試更好利用雲上虛拟機的彈性能力,去做一些微服務的自動化水準擴縮容。

随着技術進一步發展,到雲原生時代,到底什麼不同了?雲原生希望能夠把像微服務、DevOps 這些架構和理念,能夠和雲所提供的服務、能力、平台更好地進行融合、進行協同和協作。我們希望雲不光光是提供彈性實體資源,比如說存儲、計算、網絡等資源,而是能夠為微服務提供更好的一個運作環境和平台。這個需要我們做到以下兩點:

  • 對資源層面聯合優化,對資源的更優使用。
  • 對雲服務與平台的充分利用,研發、運維效率的極大提升。

這個其實是雲原生想去做的事情,就是讓我們的微服務架構和體系,能夠和雲與雲上面的服務、平台,以最佳的方式工作、協同在一起,降本提效。

二 微服務與雲原生

如果我們以微服務為中心去看待微服務與雲原生,可以從四個點講一講它們之間的關系,以及微服務在雲原生時代的演進。

  • 生命周期的管理。
  • 流量治理。
  • 程式設計模型。
  • 可信安全。

生命周期

從本質上來講,微服務就是把單體應用從一個巨型的應用拆分成數個更微小的服務,協作完成原來單體應用所提供的等效業務服務。是以,服務與服務之間會有依賴關系,服務也需要去部署到一個或多個資源上。

雲原生時代,微服務如何演進?

如上圖所示,大家可以看到,原來的單體應用與資源之間的關系其實是一對一的關系,單體應用的協同也都是一些内部協同,不存在外部動态的依賴。而當我們轉換到微服務之後,可以看到這張圖會變成網狀,變得複雜起來。

是以由于内在原因,超過 50% 的企業會認為微服務架構或采用微服務架構,其中最大的挑戰在于更為複雜的運維,也就是更為複雜的生命周期管理。

我們在今天講雲原生的根基——容器與容器服務,就在于幫助微服務解決生命周期管理以及運維管理難題,那是怎麼解決的呢?

雲原生時代,微服務如何演進?

我認為分為兩個部分:

第一部分,不同微服務之間可能存在一些異構,為了讓每一個團隊在微服務體系下發揮最大效能,我們允許不同團隊采用不同的程式設計語言,甚至不同的運作環境來去運作這些微服務。是以,我們在運維和管理微服務時,最初其實并沒有一套統一的标準去處理的異構環境,這也是為什麼後來容器這項雲原生技術變得流行起來,它的一個重要作用就是通過一層标準的封裝以及标準的運作時,來标準化微服務部署。這樣從生命周期管理的角度來看,每一個微服務之間的差異就會變少,共同點變多。

基于這個技術,後來我們又開發出另一層:容器平台,也是今天比較流行的,像 Kubernetes 。它的作用是幫助把已經标準化的微服務最便捷地運作到底層資源上面。我們講到的存儲、計算、網絡都通過 Kubernetes 這層進行了統一抽象和封裝,讓已經被容器統一的微服務能夠直接運作到 Kubernetes 平台。是以,運維人員不用再苦惱如何去把某個微服務配置設定到具體的某一個資源或計算單元上去。通過容器和容器平台,大大簡化了微服務本身的生命周期管理,簡化了微服務自身的運維管理問題,也促進了微服務更多地被企業所采用。

如果更微觀地去看,容器和容器平台具體給微服務的生命周期還提供了哪些幫助呢?

雲原生時代,微服務如何演進?

例如 Kubernetes 引入了一個非常有意思的概念,叫做 pod,一個 pod 實際上是一組容器的集合,在一個 pod 中可以運作一個或多個容器。一般來講,當我們采用微服務架構時,會把微服務的主體運作在主容器中,主容器的生命周期跟 pod 自身的生命周期是一個耦合的狀态。

除此之外,我們還會運作一些邊車容器或者叫 Sidecar 容器,為主容器提供一些輔助功能,比如說日志采集、網絡代理、身份鑒權等。我們都可以把它放 Sidecar 容器中,這樣微服務具備了 Super power,一種超能力。它除了自身提供的核心業務服務以外,我們還可以裝上盔甲,也就是動态添加一些額外的輔助能力,讓微服務管理變得更強健更強壯。

另一方面,其實 pod 這個模型還提供了一些非常有用的功能:

  • 狀态資訊。Pod 會提供一個标準接口顯示運作狀态。例如,是否已經準備好接收流量,如果準備好接收流量,那麼從 ingress 流量就可以打到微服務上。如果運作狀态不良,我們可以嘗試對這個容器進行修理、重新開機或删除,甚至是換到另一個計算單元上去運作,為微服務整體的穩定性提供了保障。
  • 位址服務。每一個 pod 都有一個标準化的 DNS 位址服務,可以被統一的尋址。這樣對于需要統一暴露出來 API 的日志、監控、追蹤能力都有着非常大的幫助,可以根據這個 DNS 的位址來通路 pod 所暴露的可觀測性資訊,便捷及時的發現運作時問題。

是以我們可以看到容器平台及容器其實在微觀上也幫助了微服務具有更多能力、具有更強的健壯性以及具有更好的可觀測性。

雲原生時代,微服務如何演進?

在這,如上圖所示,在微服務運作時這一方面,容器平台也提供了非常有效的能力幫助我們做 Day 2 的微服務更新、釋出、擴容等操作。比如 Kubernetes 提供了幾種比較典型的更新或是擴容政策:Rolling deployment、Blue-green release 等等,這些都有效簡化了我們的運維工作,提高了運維本身的确定性和自動化效率。

總而言之,在生命周期這一方面,通過使用容器及容器平台技術,大大提高了我們對于容器生命周期管控的标準化及自動化程度,節約了人力成本,提升了效率,讓更多的企業願意使用微服務這種技術。

流量治理

雲原生時代,微服務如何演進?

微服務一方面是把原來在靜态編譯時産生的能力與能力之間的關聯關系,通過架構拆分推演到動态的運作時。是以在運作時,服務與服務之間是需要進行通訊、協同,才能完成某一項具體的業務功能。當大家進行通訊、協同時,就一定要對其通訊過程進行管理,或者說要進行流量管理。例如,我們要知道怎樣從一個微服務找到另一個微服務,以及怎樣能保證一個微服務找到最佳的微服務執行個體跟它進行通訊,這是一個比較複雜的過程,其中包括 RPC 能力、服務注冊發現能力、動态配置管理能力以及服務降級能力等等。

為了減輕業務開發同學的負擔,不用重複的在每一個微服務中寫一遍微服務的流量管理的通用能力,是以大家開發了很多架構,比如在 Java 體系中,著名的 Spring Cloud 提供了一個分布式微服務管理架構;在 Go 語言的開源生态中也有像 Go Mirco 這樣的體系;在阿裡巴巴内部我們也有像 HSF 這樣的體系發展起來的微服務治理架構。

雲原生時代,微服務如何演進?

是以,從抽象層面可以看到一個服務包含了兩個層面:

雲原生時代,微服務如何演進?

一個層面是本身的業務邏輯,也就是由微服務業務開發人員去編寫的,功能實作與業務實作相關的代碼。

另一個層面是為了實作微服務與微服務之間通訊、流量、服務治理的代碼,我們會将其抽象成一個架構,如下圖中标出的 Spring Cloud。這樣的抽象帶來了一個問題,就是所有的通用能力都依賴于這個具體的架構。

雲原生時代,微服務如何演進?

假設在公司之中,除了 Spring Cloud 之外,我們去引入另外一些服務架構,如阿裡巴巴 HSF 如果希望和 Spring Cloud 架構上面編寫的微服務進行通訊的話應該如何去操作?這就要求 HSF 與 Spring Cloud 之間互聯互通以及協定之間的互相了解。但其實這些架構之間往往并不具備這個能力。更大的一個問題可能在于,雲原生時代我們允許這些微服務的研發能用不同開發語言及模型來進行程式設計。是以,架構之間的系統并不是不是一對二的關系,也不是 僅僅是 Spring Cloud 與 HSF 的關系,可能是 Java 體系與 JavaScript、Python、Go 體系這些微服務架構都需要打通的問題,它變成了一個 N to M 的 problem,來解決多語言、複雜環境中微服務的治理與管理問題。

這時,當我們有了容器、容器平台、Pod 這些抽象,能夠提供一個平台,而不是必須要完全依賴于業務中的代碼或 架構時,有沒有更好的辦法來解決剛才提到的問題?

雲原生時代,微服務如何演進?

現在有一個比較流行的概念叫 Service Mesh——服務網格。它的本質就是為了更好地解決流量治理在多語言、多環境場景下的問題,它的主要思想如下:

第一就是希望把流量管理的這些架構能力從耦合在業務的二進制中抽象、剝離出來,形成一個流量管理的單獨程序,并以 Sidecar 的模式部署在 Pod 中。通過作業系統級别的透明流量劫持工作,把所有的微服務之間的流量劫持到 Sidecar 中,然後通過 Sidecar 與 Sidecar 之間通訊進行流量的轉發與管理。這樣問題就簡單多了,我們隻需要讓流量管理的 Sidecar 之間互相通訊、能夠進行互聯互通。目前比較知名、流行的開源流量劫持和管理 Sidecar 實作叫做 Envoy。

當然,單單有了這層流量劫持與管理還是不夠的,還需要管控平面的支援。比如原來微服務體系做的服務注冊、服務發現以及流量觀測還是需要的,這些政策和規則需要下發給流量管理的 Sidecar 代理。是以,我們還需要建構一個管控平面來管理在 Pod 中部署的流量管理的資料平面的單點,讓它們形成一個網狀,形成一個叢集。是以我們需要有一些管控平面的能力,在開源中比較流行的一個管控平面實作叫 Istio。主要實作了三個能力:流量的配置、流量的安全、流量的觀測。

我們認為在雲原生這個逐漸平台化的時代,大部分新的應用及場景都會嘗試選用基于 Service Mesh 的技術進行微服務的流量治理。

程式設計模型

請求驅動

請求驅動,也就是支援基于請求的動态彈性伸縮并且簡化請求處理邏輯。有些同學可能把這個模型稱之為 Event-driven,也就是事件驅動,但是請求驅動實際是事件驅動中的一個分支。

雲原生時代,微服務如何演進?
雲原生時代,微服務如何演進?

什麼是請求驅動呢?從傳統的微服務架構看,當一個外部系統請求進來後,一般都會經過一個 L4/L7 的負載均衡,然後給到不同的微服務執行個體上面。在同一個微服務執行個體本身程序的内部,一般會有兩塊邏輯,第一塊邏輯是請求管理,它可能是一個 HTTP Server 和一些 Handlers,有一些隊列管理、請求分發等能力。這些請求最終會送出到第二個邏輯部分,processor 也就是真正的請求業務處理邏輯中,真正的處理并且相應這些請求。

這個架構會帶來兩個問題:

  • 請求管理的邏輯在不同的微服務架構實作中都要去寫一遍,比如 Java、Go 或 Python 都要有自己的請求管理邏輯。
  • 請求管理和請求處理形成耦合關系。是以,在這個架構下不存在一個全局獨立的可以感覺請求以及進行流量管理的控制層。隻有到了微服務執行個體自身的處理層,才能解析這個請求。這時候即便這個微服務執行個體已經過載,也很難把請求再轉發給其他微服務執行個體進行負載均衡了。

請求驅動系統就是嘗試去解決這兩個問題,我們嘗試在微服務中做一個請求驅動的解耦操作。

首先把外部系統傳輸過來的請求都進行一次标準化,我們有一個擴充卡,進行标準化之後,把它放到一個請求負載均衡器中,這個負載均衡已經能了解請求本身的語義,它就能驅動請求處理的邏輯進行請求處理。當請求處理單元不夠時,可以通過請求處理的管理器進行擴容;當請求處理的邏輯單元比較多時,還可以進行縮容,這樣就可以節約成本。另外,開發人員也不用再去實作請求管理邏輯,降低了開發成本。

剛才講的請求驅動模型可以分為三部分:

雲原生時代,微服務如何演進?
  • 請求的标準化
  • 請求的路由
  • 請求的處理

其實,如果把外部系統的請求标準化,加上請求路由、處理管理,而不包含業務代碼,就會組成我們常說 Serverless 概念。這也就是一種把微服務體系和平台化的 Serverless 體系融合的一個過程。

Serverless 平台有阿裡雲 FaaSS、SAE,AWS 有 Lambda、Google 推出了 CloudRun、Azure 有 Functions。如果大家希望自己能夠建構一個 Serverless 平台,如請求标準化,也有像 Cloud Events 這樣的開源請求标準, Knative 這樣的處理路由以及處理請求的水準擴充能力元件,可以利用 Kafka 或者 RocketMQ 來做請求本身的持久化以及請求本身的轉發。

分布式運作時

在程式設計模型中的分布式運作時,也就是我們希望微服務能夠有更好的多語言環境支援、環境可移植性并能做到極速啟動。

雲原生時代,微服務如何演進?

單體應用時代,我們的業務代碼跟中間件代碼耦合在一起,而且是一份部署的執行個體;當到了微服務時代,通過像 Service Mesh 服務網格進行流量管理之後,可以看到我們的業務代碼和流量管理代碼實際上是可分離的,隻有部分中間件的代碼仍然和部分業務代碼耦合在一起形成一個二進制。

為了能夠做到充分的多語言能力支援、環境的可移植性,我們希望能夠把剩餘的中間件代碼也從業務中解耦出來,這項技術叫做運作時解耦。它的根本理念是通過向業務代碼提供一個标準的可擴充 API,并且是一個多語言可支援、輕量級的 API,通過調用 API 來實作中間件的功能,我們把中間件的能力像流量管理一樣下沉到一個 Sidecar 中,用一種語言進行統一實作,然後設計一個可拔插的模式,讓大家能夠拔插更多中間件的能力。

Dapr

這項技術比較領先的一個實踐是微軟去年推出的一個分布式運作時,叫做 Dapr。

雲原生時代,微服務如何演進?

Dapr 向業務的代碼暴露了兩個 API,一個是 HTTP 的 API,另外一個是 grpc 的 API。這兩個 API 都非常輕量級,并能夠跨多種語言,Dapr 本身作為分布式運作時,可以對接多種中間件系統,向上通過标準的 API 屏蔽不同系統之間的差異性,提供一定的程式設計界面界面統一。代碼實作上把中間件的代碼從應用級别抽離到 Sidecar 中,如上圖所示,我們在業務上面隻需要寫業務的代碼,其他代碼幾乎都被基于 Dapr 的平台所接管。

雲原生時代,微服務如何演進?

Dapr 本身分為兩部分:第一部分是 Dapr 向 Application 暴露的 API,另一部分是 Dapr 的架構層。

通過 Dapr 的架構層,我們可以接入各種不同的 Dapr 相關實作:Resource bandings 如 Kafka/SQS、管理資料的如 Redis/cassandra、或者我們去做 Publish & subscribe 如 RabbitMQ、甚至 Distributed Tracing 如 Prometheus/Open tracing 等等,都可以接入到 Dapr 這套架構裡,然後通過統一的标準 HTTP、gRPC API 提供給業務代碼、應用代碼去使用,這樣就做到了業務代碼與中間件、流量管理能力的更徹底的解耦,應用的開發人員也能夠更專注、更自由地去關注業務代碼研發。

可信安全

因為微服務與微服務之間需要有網絡通訊,需要有安全可信的認證。傳統做法就是把微服務放到一個可信網絡環境中,假設網絡環境中所有通訊、執行的應用或微服務都是受信的,它們可以自由通訊或交流,可能有一些輕量級的鑒權與授權進行一定的安全防護措施。

雲原生時代,微服務如何演進?

但這個模型會帶來一種風險,當有微服務入侵到這個可信網絡之中,它會對整個微服務體系造成極大的安全隐患,因為可信網絡中的内部防範一定程度上是比較欠缺的。

雲原生時代,微服務如何演進?

另外,經常會有可信網絡與可信網絡之間的微服務互相調用或鑒權的問題,常見解決方法是通過 VPC peering 或者通過 gateway 網絡的網關打通。利用一個可信通道保證微服務與微服務之間的網絡層面可信的調用。但同樣引出一種問題,比如在另外一個可信網絡中被入侵,便可以攻擊到其它相連的可信網絡,也增大了受攻擊的可能性。

雲原生時代,微服務如何演進?
雲原生時代,微服務如何演進?

在微服務時代,我們思考是否有更好的解決方式,不去假設網絡是完全可信的環境。是以,提出了一個叫做微服務或應用可信安全。也就是微服務與微服務或者機密檔案之間的每一次通訊,都基于身份體系。微服務會提供給它所溝通、協同的目标對象一個身份認證。就好比我們通過浏覽器通路 HTTPs 網站,這些網站需要提供證書,我們的微服務也需要提供一個自身的身份認證,這樣接收方就可以通過平台進行認證且檢視授權。隻有這些認證都通過,才會和開始微服務的通訊。

實際上,利用平台的特點在網絡層面内部以應用為中心,又建設起一套基于統一身份認證授權的體系。

雲原生時代,微服務如何演進?

但這個體系還是比較難建構的,相當于要在不完全受信的網絡中,需要有一個可以信任的平台層或中間層,也就類似 PKI 中的 CA 機制。在 HTTPs 上,比如說我們要信任一個 CA,可能需要提前講證書預置在作業系統中,從安裝時就要預置好,才能提供一個更為安全的端到端的可信,否則是無法建構好這個信任鍊的。同樣的,在雲環境中也需要這個機制。雲本身是一個可控平台,通過從雲最底層的硬體機制,到雲上運作的 OS 上,再到最終向上部署微服務的平台層,我們都要建立起來了一個可證的授信鍊,最終給每一個微服務提供自身的身份 ID 以及授權可證的授權資訊,這樣微服務才能提供統一可驗證、可證明的身份。也就是說在雲原生時代,通過平台思維能夠給微服務安全提供更大的價值。

另外在平台與平台之間或網絡與網絡之間,也可以通過平台級别的可信授信來建立關聯的關系,讓不同平台之間的微服務也能産生信任關系。為了打通不同的平台,有一個開源項目叫做 spiffe,它提供了統一的标準身份 ID 以及如何統一标準地進行授權資訊的可證和授權資訊的認證。

雲原生時代,微服務如何演進?

三 EDAS

其實上面講了那麼多,可以發現在開源開放領域不停地有新的技術衍生出來,不管是與微服務流量治理相關,還是與微服務生命周期相關,又或是微服務的可信安全、程式設計模型,如果大家自己嘗試去建構這種能力或平台,一般還是需要花費非常大的時間和精力的。

雲原生時代,微服務如何演進?

是以阿裡雲最近更新了雲上的服務——EDAS,把 EDAS 從傳統的面向微服務的管理體系,基于雲原生的基礎設施變成了一個雲原生應用 PaaS,提供容器的生命周期管理、微服務治理、可觀測性、安全流量治理等能力,讓阿裡雲使用者能最大化享受到微服務在雲原生時代的紅利,同時又不需要花費時間去建構這樣的平台。

是以推薦對雲原生微服務感興趣的同學可以嘗試使用 EDAS。

四 雲原生微服務

在雲原生時代,微服務的特點:

  • 平台化,利用雲作為一個平台,如微服務架構進行更多的賦能。
  • 标準化,我們希望微服務本身的部署、運維,微服務之間與其它服務之間的通訊都能做到标準化,讓服務與服務之間的互聯互通變得更容易,服務能夠跨到不同的平台上,做到一次編寫、一次定義、多處運作。
  • 微服務輕量化,讓研發人員關心核心業務代碼、業務邏輯的研發,而不是複雜的微服務治理相關的邏輯研發。
  • 微服務的産品化。我們希望能建構微服務相關的産品,以産品化的方式支援大家使用微服務架構,讓它變得更好用、更易用。

五 全球開源微服務架構活躍度報告

雲原生時代,微服務如何演進?
雲原生時代,微服務如何演進?

我們最近花了很大精力收集在雲原生時代比較活躍的一些微服務項目,然後發現了幾個特點:

  • quarkus 這個項目非常活躍,它可以幫助 Java 或 Java 生态盡量輕量化,适應雲原生時代我們對彈性和高效啟動速度的要求。
  • Spring Cloud 的上升趨勢還是非常好的,作為 Java 裡非常典型的微服務架構,在阿裡巴巴我們也是在 Spring Cloud 生态中進行深耕,現在最流行的一個Spring Cloud 雲服務提供廠商就是 Spring Cloud Alibaba。
  • 最後像 Dubbo,還有阿裡正投資很多人力去共建的 Dapr 項目其實也比較活躍。