傳統微服務框架如何無縫過渡到服務網格 ASM

語言: CN / TW / HK

作者:宇曾

背景

軟體技術的發展歷史,從單體的應用,逐漸演進到分散式應用, 特別是微服務理念的興起,讓大規模、高併發、低延遲的分散式應用成為可能。雲原生時代下,微服務框架本身也在不斷地進化和迭代演進。

微服務框架一般會涉及到以下幾個知識點:

1.png

本文我們著重探討以下三大微服務框架:

  • SpringCloud
  • Dubbo
  • ServiceMesh (新生代)

這三款不同的框架對服務治理領域的功能點覆蓋度弱有差異。本文不著重探討這幾個框架的誰優誰劣,主要來探討下如何從傳統的微服務框架 Dubbo 、SpringCloud 無縫過渡到 ServiceMesh 架構。當下 ServiceMesh 領域最火熱的專案非 Istio 莫屬。

阿里雲服務網格 ASM 基於 Istio ,對 Istio 進行了雲上託管和適配,並且新增了相關功能,以及大規模服務網格場景下的效能優化等。作為業內首個全託管 Istio 相容的阿里雲服務網格產品 ASM,一開始從架構上就保持了與社群、業界趨勢的一致性,控制平面的元件託管在阿里雲側,與資料面側的使用者叢集獨立。ASM 產品是基於社群 Istio 定製實現的,在託管的控制面側提供了用於支撐精細化的流量管理和安全管理的元件能力。通過託管模式,解耦了 Istio 元件與所管理的 K8s 叢集的生命週期管理,使得架構更加靈活,提升了系統的可伸縮性。從 2022 年 4 月 1 日起,阿里雲服務網格 ASM 正式推出商業化版本, 提供了更豐富的能力、更大的規模支援及更完善的技術保障,更好地滿足客戶的不同需求場景, 詳情可見產品介紹:

http://www.aliyun.com/product/servicemesh

下面我們一起來看下傳統微服務遷移到服務網格技術棧會有哪些已知問題,以及阿里雲服務網格 ASM 又是如何無縫支援 SpringCloud 、Dubbo 這些服務的。

關注【阿里云云原生】公眾號,回覆關鍵詞【0621】獲取文中程式碼壓縮包下載地址!

傳統微服務遷移到服務網格的一些已知問題和場景

常見的幾個問題

  • 服務容器化後,服務 deployment 滾動更新,服務例項的 IP 是經常變化的,對應服務例項IP 同步到註冊中心會有延遲,這個過程會導致部分業務請求出現 503。

  • Istio 社群版本對非 HTTP 、gRPC 的其他 rpc 協議支援有限,無法提供統一形態的路由管理,以及相關治理能力。

  • 因 Istio 本身設計的服務路由模型依賴服務間請求為 ServiceName 或 ClusterIp ,SpringCloud 服務沒有辦法直接 Mesh 化,Dubbo 服務因基於 interface 的服務呼叫設計,interace 在 Dubbo 協議請求的上下文有傳遞,雖然不受該模式的限制,但 Istio 社群版本對 Dubbo 路由的支援卻沒有對應的 RDS 支援,無法直接採用社群版本的 VirtualService 配置 Dubbo 路由。

除了以上一些常見問題,還有一些具體的業務場景在業務雲原生化過程中經常遇到。

場景 1:容器叢集內外服務如何互通

  • 部分業務容器化,遷移到 Kubernetes 叢集

  • 仍舊有一些遺留服務需要在 ECS 雲主機在部署

2.png

通過 ASM 對接註冊中心,可以實現容器叢集內外服務互通,並且保留服務治理能力。並且容器化業務服務通過 ASM 服務網格化託管,將服務治理能力下沉到 Sidecar ,方便業務快速獲得 Istio 帶來的宣告式配置,進行流量管理、灰度釋出等服務治理編排能力,同時天然獲得了對接 Trace、Log、Metrics 可觀察的三大件能力。

場景 2:多語言業務互通

隨著雲原生化浪潮的到來,業務一般更加複雜多樣,很多客戶因為業務發展需要,採用了多語言甚至多套開發框架,不同的語言服務之間如何進行互聯互通,或者是否有一種統一的服務框架來管理這些多語言服務?

3.png

ASM 服務網格針對以上客戶的相關場景,以及遇到常見問題,基於 Istio 社群版本進行了功能擴充套件,可以支援 SpringCloud 、Dubbo 服務無縫遷移服務網格,也就是業務不需要進行任何程式碼修改,即可天然享受服務網格提供的能力,以下我們對 SpringCloud 和 Dubbo 分別進行具體的解析說明。

管理 SpringCloud 服務

SpringCloud 服務通訊是採用 HTTP 協議,Istio 對 HTTP 協議的支援非常友好,我們只需要解決 Istio 如何管理 SpringCloud 服務即可,也就是解決 SpringCloud 服務請求如何適配 Istio 依賴的 Servicename 或者 ClusterIp 問題。

4.png

簡單地說,就是服務網格因為採用 Sidecar 模式,需要知曉請求發出的流量目標服務是誰,並且這個資訊需要在 Http 請求的 Host 欄位下進行宣告。

方案 1:採用 EnvoyFilter + Lua 方式

核心實現是通過 EnvoyFilter 下配置了一段 Lua 邏輯修改了服務訂閱請求的返回,將服務訂閱返回的目標 IP 地址修改為對應的服務名。具體 Demo 例子可以參考 ASM Help 文件: 

http://help.aliyun.com/document_detail/383257.html

但該方案因為需要理解具體的服務訂閱協議,目前僅支援 Nacos, 不支援其他非 Nacos 註冊中心,雖然我們提供了一些服務註冊中心遷移的方案,  因為各方面的原因,使用者可能不太想修改程式碼適配註冊中心。基於此,我們提供了方案2 可以適配支援任意註冊中心。

方案 2:通過 Reverse DNS Filter 反向查詢得出 ServiceName

方案 1 目前僅能支援 Nacos , 不少使用者看到後紛紛反饋是否可以支援 Eureka、ZooKeeper 等服務註冊中心,基於此,我們推出瞭如下通用解決方案:

5.png

btw, 因為 Istio 天然支援 gRPC 協議,而 Dubbo3 新版協議 triple 基於 gRPC , Dubbo3 服務可以比較優雅的上 Mesh,

如上方案也適用於 Dubbo3 服務。

小結:通過以上兩個方案(推薦使用方案 2) 我們解決了 SpringCloud 服務適配 Istio 路由模型的問題,從此 SpringCloud 就可以享受 Istio 全量的能力了,而且無需進行任何程式碼修改。

當然,如果使用者願意修改程式碼,我們更推薦客戶去除原有的 SpringCloud 下的類似負載均衡、熔斷、限流等相關注解,因為在 Mesh 場景下,原有的能力已經沒有必要了。

方案2 ReverseDNS Filter 方案已在ASM 1.13 版本內建,預計6月底釋出上線

管理 Dubbo 服務

這裡我們說到 Dubbo 服務指的是 Dubbo2,Dubbo3 採用如上類似方案即可,我們也在對接 Dubbo3 社群,支援 Dubbo3 的 Proxyless Mesh 模式。目前 Dubbo2 依然存在大量的使用者,因此阿里雲服務網格對 Dubbo2 也提供了深度支援,以下提到的 Dubbo 都是隻 Dubbo2 版本。

Dubbo 使用者大多數使用 Nacos 或者 ZooKeeper 註冊中心,ASM 產品層面目前支援 MSE Nacos 註冊中心。

只需要簡單地在 ASM 設定選單下關聯 MSE Nacos 例項即可發現對應 Nacos 下的服務資訊。

6.png

支援 Dubbo + Nacos 服務遷移到 ASM

整體架構圖如下:

7.png

相關文件:

  • 託管 Dubbo 服務

  • 管理 Dubbo 服務流量

  • Dubbo 服務的虛擬服務引數說明

  • 整合自建 Prometheus 實現 Dubbo服務可觀測性

ASM 在 Istio 社群版本的 VirtualService 基礎上擴充套件支援了 Dubbo 路由,一個較為複雜的配置樣例如下:

apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: demoservice0 spec: hosts: - providers:com.alibaba.edas.DemoService0 dubbo: - routes: - match: - method: nameMatch: exact: "sayHello" argc: 1 args: - index: 1 strValue: patterns: - exact: "jack" type: java.lang.String route: - destination: subset: v1 weight: 100 - match: - method: nameMatch: exact: "sayHello" argc: 1 args: - index: 1 strValue: patterns: - exact: "lily" type: java.lang.String headers: app: patterns: - exact: "consumer1" route: - destination: subset: v2 weight: 100 services: - prefix: providers:com.alibaba.edas.DemoService0

Dubbo 路由的具體 Spec 定義和例子說明請參考如上 Dubbo 服務治理系列文件

支援 Dubbo  + ZooKeeper

對於 Dubbo 開源使用者,除了 Nacos 外,也有較多使用者使用 ZooKeeper 註冊中心,但 ZooKeeper 目前官方並未提供針對 Istio 服務發現能力,也就是 Istio 依賴的 MCP over XDS  協議的支援。

MCPBridge 元件解決了這個問題,在阿里雲服務網格 ASM 場景下,具體實現方案如下:

8.png

因註冊中心的多樣性,後續MCPBridge 將會提交給開源社群,歡迎大家一起來維護。

使用者可以通過下載 MCPBridge Helm 安裝包,手動安裝 MCPBridge 到業務部署所在的 ACK 叢集。

安裝方法很簡單,下載完成後解壓 Helm 安裝包,然後在目錄下執行:

helm install -f values.yaml mcp-bridge .

安裝完成後,mcp-bridge 會通過 SLB 提供一個 VPC 內網地址,需要將 Istiod 對應的 ConfigSource 關聯該地址。ASM 此功能目前白名單開放中,需要提工單或者加文章結尾的群聯絡產品運維人員。

安裝完成後,接著我們就可以給它配置上游註冊中心地址為 ZooKeeper  ,若環境沒有可用的 ZooKeeper 伺服器,可以通過阿里雲 mse ZooKeeper 快速建立一個,如下:

9.png

給 MCPBridge 元件配置它需要關聯的註冊中心很簡單,只需要建立一個 MCPBridge CR 即可,具體配置格式如下:

檔案:zk-mcpbridge.yaml

apiVersion: istio.aliyun.cloud.com/v1 kind: McpBridge metadata: name: default namespace: istio-system spec: registries: - domain: mse-7e74ff00-zk.mse.aliyuncs.com ### zookeeper 地址 name: zookeeper port: 2181 type: zookeeper

kubectl apply -f zk-mcpbridge.yaml  生效後,MCPBridge 元件就會自動同步 ZooKeeper 下dubbo 節點下的服務資訊到 istiod 了。

若想體驗 MCPBridge 支援 Dubbo  + ZK 的具體示例,可以下載測試示例: dubbo-zk-demo.tar.gz

檔案包下面包含了上面 McpBridge 這個 yaml 配置以及測試用的 dubbo demo 服務例子。

[email protected]:~/test/mcpbridge/dubbo-zk-demo# tree . . ├── dubbo-services.yaml ## dubbo + zk註冊中心測試服務例子 ├── zk-mcpbridge.yaml ## mcpbridge zk 配置,需要對應修改zk地址 └── zk-registry-service-alias.yaml ## zk地址的服務別名,需要對應修改zk地址

接下來我們簡要說明下如何來使用這個 Demo 例子。

當把 dubbo-zk-demo.tar.gz下載並解壓完成後,我們首先需要將 yaml 下 zk 地址 "mse-7e74ff00-zk.mse.aliyuncs.com"  修改為實際對應的 zk 服務地址(該地址需要確保 MCPBridge 元件可以訪問),地址修改完成後,在 dubbo-zk-demo 檔案目錄下執行如下命令:

kubectl create ns dubbo kubectl label ns dubbo istio-injection=enabled kubectl apply -f .

然後再通過命令 kubectl get pods -n dubbo 檢視確認對應 dubbo 服務 consumer 、provider 是否啟動成功,

[email protected]:~/test/mcpbridge# kubectl get pods -n dubbo NAME READY STATUS RESTARTS AGE dubbo-consumer-zk-5cd8f6c6bf-bscd2 2/2 Running 0 83m dubbo-provider-zk-v1-54cd888957-k7bg4 2/2 Running 0 83m dubbo-provider-zk-v2-cf58ccc79-sg94l 2/2 Running 0 83m

啟動成功後,我們回到 Zookeeper 下,可以看到已經有服務註冊資訊報上來了:(dubbo 節點下)

10.png

接著,我們將 consumer 服務對映到 ASM 閘道器下進行測試訪問,通過 ASM 控制檯我們可以快速地建立一個 ASM 閘道器,若是採用 CICD 或者 GitOps 等方案,也可以直接通過建立 IstioGateway Yaml 的方式來建立。

11.png

12.png

閘道器實體建立成功後(gateway deployment、svc 等),我們還需要配置邏輯閘道器,只需要兩步即可;

  • 建立一個閘道器規則(istio 下的 gateway CRD), 宣告一個邏輯閘道器,以及這個邏輯閘道器(test-gateway) 繫結的具體域名和宣告埠以及協議型別

  • 配置閘道器路由,將 /sayHello 請求轉發給 dubbo-consumer-zk.dubbo.svc.cluster.local 目標服務

閘道器規則和閘道器路由可以參考如下 Yaml, 我們只需將這個 Yaml 儲存為本地檔案,然後在 asm 叢集下 kubectl apply 即可。

```

apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: test-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"


apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: consumerhttp spec: hosts: - "*" gateways: - test-gateway http: - match: - uri: prefix: /sayHello route: - destination: host: dubbo-consumer-zk.dubbo.svc.cluster.local ##對應consumer服務的k8s service name port: number: 17080 ```

閘道器規則和路由配置生效後,我們可以通過瀏覽器或者終端命令方式:

curl http://$INGRESS_GATEWAY_IP/sayHello/world  來訪問前面部署的 Dubbo demo 服務,執行如下命令,可以看到執行後輸出的相關結果:前後請求兩次負載均衡到了 Provider 的 v1 、v2 版本。

``` #export INGRESS_GATEWAY_IP=YOUR_GATEWAY_IP

#curl http://$INGRESS_GATEWAY_IP/sayHello/world

V2 Gray1: hello world - 172.22.32.143:20880

#curl http://$INGRESS_GATEWAY_IP/sayHello/world

V1 Gray1: hello world - 172.22.32.39:20880 ```

更多流量管理、灰度釋出、可觀測例子可以參考 Istio 以及 ASM 下 Dubbo 服務治理的相關文件來配置。

總結

針對傳統微服務框架 SpringCloud 和 Dubbo, 阿里雲服務網格 ASM 針對客戶常用的場景需求以及遇到的問題,基於 Istio 進行擴充套件支援,可以無縫相容管理 SpringCloud 、Dubbo 服務,並提供 Istio 原生的服務治理能力。

阿里雲服務網格 ASM 作為託管服務網格的先行者,已經收穫了大量的使用者落地,這些使用者更加堅定了我們做這個產品的信心。服務網格不再是成堆的 buzzword,而是真真實實應用到生產環境,處理服務治理領域一個又一個的技術問題。迴歸本質,服務網格還是要解決真真切切的業務問題。

服務網格社群在蓬勃發展,ASM 產品仍有需要完善的地方,但它已經在市場驗證中獲得了前行的力量。服務網格的史詩故事才剛剛開始,歡迎加入釘釘群交流探討~

13.jpeg