自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Kitex Proxyless 之流量路由:配合 Istio 與 OpenTelemetry 實現全鏈路泳道

開發(fā) 架構
Kitex Proxyless 簡單來說就是 Kitex 服務能夠不借助 envoy sidecar 直接與 istiod 交互,基于 xDS 協(xié)議動態(tài)獲取控制面下發(fā)的服務治理規(guī)則,并轉換為 Kitex 對應規(guī)則來實現一些服務治理功能(例如本文的重點:流量路由)。

1. 引言

1.1 Kitex Proxyless

Kitex 是字節(jié)跳動開源的 Golang RPC 框架,目前已經原生支持了 xDS 標準協(xié)議, 支持以 Proxyless 的方式被 ServiceMesh 統(tǒng)一納管。

  • 詳細設計見:Proposal: Kitex support xDS Protocol · Issue #461 · cloudwego/kitex (https://github.com/cloudwego/kitex/issues/461)
  • 具體使用方式見:官方文檔(https://www.cloudwego.io/zh/docs/kitex/tutorials/advanced-feature/xds/)

Kitex Proxyless 簡單來說就是 Kitex 服務能夠不借助 envoy sidecar 直接與 istiod 交互,基于 xDS 協(xié)議動態(tài)獲取控制面下發(fā)的服務治理規(guī)則,并轉換為 Kitex 對應規(guī)則來實現一些服務治理功能(例如本文的重點:流量路由)。

基于 Kitex Proxyless,讓我們實現 Kitex 能夠無需代理就可以被 ServiceMesh 統(tǒng)一管理,進而實現多種部署模式下的 治理規(guī)則 Spec、治理控制面、治理下發(fā)協(xié)議、異構數據治理能力 的統(tǒng)一。

圖片

1.2 流量路由

流量路由是指,能夠將流量根據其自身特定的元數據標識路由到指定目的地。

流量路由屬于服務治理中比較核心的能力之一,也是 Kitex Proxyless 優(yōu)先支持的場景之一。

Kitex 基于 xDS 實現 流量路由 的方案大致如下:

圖片

具體流程:

  1. 增加一個xDS Router MW 來負責 Pick Cluster(路由),并 watch 目標服務的 LDS 及 RDS。
  2. 感知 LDS 變化,并提取目標服務的 LDS 中的 Filter Chain 及其 inline RDS。
  3. 感知 RDS 變化,根據VirtualHost 和 ServiceName 來匹配(支持前綴、后綴、精確、通配),獲取目標服務的路由配置。
  4. 遍歷處理匹配到的 RDS 中的路由規(guī)則,路由規(guī)則主要分為兩部分(參考:路由規(guī)范定義):
  1. Match(支持前綴、后綴、精確、通配等),目前版本我們支持以下兩種即可
  1. Path(必須項):從rpcinfo 提取 Method進行匹配。
  2. HeaderMatcher(可選項):從metainfo 中提取對應元數據 KeyValue,并進行匹配。
  1. Route:
  1. Cluster: 標準 Cluster。

  2. WeightedClusters(權重路由): MW 內根據權重來選擇 cluster。

  3. 將選擇到的 Cluster 寫入 EndpointInfo.Tag,用于之后的服務發(fā)現。

可以看到,流量路由其實是一個根據一定規(guī)則選擇對應 SubCluster 的流程。

2. 全鏈路泳道

基于流量路由能力,我們可以延伸出很多使用場景,如:A/B 測試、金絲雀發(fā)布、藍綠發(fā)布等等,以及本文重點:全鏈路泳道 。

全鏈路泳道可以理解成是對一組服務實例按照一定方式進行拆分(例如部署環(huán)境),并基于全鏈路灰度路由能力,讓流量能夠精準按照規(guī)則在指定服務實例泳道中流動(邏輯上如同游泳場中的泳道)。

在 Istio 中我們一般會通過 DestinationRule 的 subset 對實例進行分組,將一個服務拆分成不同子集(例如:按照版本、區(qū)域等屬性拆分),然后配合 VirtualService 來定義對應的路由規(guī)則,將流量路由到對應子集中,從而完成泳道中的單跳路由能力。

不過單單只有流量路由能力,還不足以實現全鏈路泳道 , 因為當一個請求跨越多個服務的時候,我們需要有一個比較好的機制能夠準確識別出該流量,并基于這個特征來為每一跳流量配置路由規(guī)則。

如下圖所示:假設我們要實現一個用戶的請求能夠精確灰度到 service-b 的 v1 版本。最先想到的做法可能是所有請求都帶上 ??uid = 100?? 的請求頭,然后配置對應 VirtualService 來根據 header 里的 ??uid = 100?? 匹配。

圖片

但這樣的做法有幾個明顯的缺點:

  1. 不夠通用: 以具體某個業(yè)務屬性標識(如:uid)作為流量路由匹配規(guī)則,我們需要將這個業(yè)務屬性手動在全鏈路里透傳,這本身對業(yè)務侵入性較大,需要業(yè)務配合改造。并且當我們要使用其他業(yè)務屬性的時候,又需要全鏈路業(yè)務都改造一遍,可想而知,是非常不通用的做法。
  2. 路由規(guī)則容易頻繁變動,容易造成規(guī)則臃腫: 以具體某個業(yè)務屬性標識(如:uid)作為流量路由匹配規(guī)則,假設我們要換一個業(yè)務屬性,或者給其他用戶設置路由規(guī)則的時候,得去改造原有的路由規(guī)則,或者針對不同業(yè)務屬性重復定義多套路由規(guī)則,很容易就會造成路由臃腫,以至于難以維護。

因此,要實現全鏈路的流量路由統(tǒng)一,我們還需要額外借助一個更通用的 流量染色 與 染色標識全鏈路透傳 能力。

2.1 流量染色

流量染色是指對請求流量打上特殊標識,并在整個請求鏈路中攜帶這個標識,而所謂的全鏈路泳道,就是整個鏈路基于統(tǒng)一的灰度流量染色標識來設置流量路由規(guī)則,使得流量能夠精準控制在不同泳道中。

通常我們會在網關層進行流量染色,通常會根據原始請求中的元數據,來進行一定規(guī)則(條件、比例)轉換成對應的染色標識。

  • 按條件染色:當請求元數據滿足一定條件之后,就給當前請求打上染色標識,如:請求頭中 uid=100、cookie 匹配等等。
  • 按比例染色:按照一定比例,給請求打上染色標識。

有了一套統(tǒng)一的流量染色機制之后,我們配置路由規(guī)則的時候,就不需要關心具體的業(yè)務屬性標識了,只需要根據 染色標識 來配置即可。

將具體的業(yè)務屬性抽象成條件染色規(guī)則,使其更通用,即使業(yè)務屬性發(fā)生了變化,路由規(guī)則也無需再頻繁變動了。

2.2 染色標識全鏈路透傳

染色標識通常會依靠 Tracing Baggage 來透傳,Baggage 是用于在整個鏈路中傳遞業(yè)務自定義 KV 屬性,例如傳遞流量染色標識、傳遞 AccountID 等業(yè)務標識等等。

圖片

要實現流量染色標識在全鏈路透傳,我們通常會借助 Tracing Baggage 機制,在全鏈路中傳遞對應染色標識,大部分 Tracing 框架都支持 Baggage 概念機能力,如:OpenTelemetry、Skywalking、Jaeger 等等。

有了一套通用的全鏈路透傳機制,業(yè)務方就只需要接入一遍 tracing 即可,無需每次業(yè)務屬性標識發(fā)生變化就配合改造一次。

下面會借助一個具體的工程案例介紹,來介紹并演示如何基于 Kitex Proxyless 和 OpenTelemetry Baggage 實現全鏈路泳道功能。

3. 案例介紹:Bookinfo

該案例是使用 Hertz、Kitex 重寫經典的 Istio Bookinfo 項目:

  • 使用 istiod 來作為xDS server,作為 CRD 配置和下發(fā)的入口;
  • 使用 wire 來實現依賴注入;
  • 使用 opentelemetry 來實現全鏈路追蹤;
  • 使用 Kitex-xds 和 opentelemetry baggage 來實現proxyless 模式下的全鏈路泳道;
  • 使用 arco-design 和 react 實現一個Bookinfo UI。

3.1 架構

整體架構與 Bookinfo 保持一致,分為四個單獨的微服務:

  • ??productpage??. 這個微服務會調用 details 和 reviews 兩個微服務;
  • ??details??. 這個微服務中包含了書籍的信息;
  • ??reviews??. 這個微服務中包含了書籍相關的評論。它還會調用 ratings 微服務;
  • ??ratings??. 這個微服務中包含了由書籍評價組成的評級信息。

??reviews?? 微服務有 3 個版本:

  • v1 版本會調用ratings 服務,并使用 1 顆 ?? 顯示評分;
  • v2 版本會調用ratings 服務,并使用 5 顆 ???????????? 顯示評分;
  • v3 版本不會調用ratings 服務。

圖片

3.2 泳道示意圖

整體區(qū)分成 2 個泳道:

  • 基準泳道  未被染色的流量會被路由到基準泳道中。
  • 分支泳道  被染色的流量會被路由到 reviews-v2 ->ratings-v2 的分支泳道中。

圖片

3.3 流量染色

網關統(tǒng)一負責對流量進行染色,例如請求 header 中 uid=100 的流量都統(tǒng)一進行染色,為請求攜帶上 ??env=dev?? 的 baggage 

圖片

染色方式可以根據不同的網關實現具體選擇,例如當我們選擇 istio ingress 作為網關的時候,我們可以借助 ??EnvoyFilter?? + ??Lua?? 的方式來編寫網關染色規(guī)則。

3.4 為服務實例打標

  1. 為對應workload 打上對應 version 標識。

以 reviews 為例,只需要給對應 pod 打上 version: v1 的 label 即可。

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/instance: reviews
app.kubernetes.io/name: reviews
name: reviews-v1
spec:
selector:
matchLabels:
app.kubernetes.io/instance: reviews
app.kubernetes.io/name: reviews
version: v1
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
labels:
app.kubernetes.io/instance: reviews
app.kubernetes.io/name: reviews
version: v1
...
  1. 基于DestinationRule 為服務設置一系列的 subsets:
  • Productpage: v1
  • Reviews: v1、v2、v3
  • Ratings: v1、v2
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2

3.5 流量路由規(guī)則

網關已經將請求頭中攜帶了 uid=100 的流量進行了染色,自動帶上了 ??env=dev?? 的 baggage,因此我們只需要根據 header 進行路由匹配即可,下面是具體的路由規(guī)則配置示例:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
baggage:
exact: "env=dev"
route:
- destination:
host: reviews
subset: v2
weight: 100
- route:
- destination:
host: reviews
subset: v1
weight: 80
- destination:
host: reviews
subset: v3
weight: 20

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
baggage:
exact: "env=dev"
route:
- destination:
host: ratings
subset: v2
weight: 100
- route:
- destination:
host: ratings
subset: v1
weight: 100

3.6 查看效果

3.6.1 基準泳道

入口流量請求頭中不帶 uid=100 的請求,會自動路由到基準泳道服務,reviews v1 和 v3 服務間輪詢,展示的效果是評分為 0 或 1 隨機。

圖片

3.6.2 分支泳道

  1. 我們這邊通過瀏覽器 mod-header 插件,來模擬入口流量請求頭中攜帶了uid=100 的場景。

圖片

2.  再點擊刷新按鈕,可以發(fā)現請求打到了分支泳道,流量泳道功能成功生效。

圖片

4.  總結與展望

至此我們已經基于 Kitex Proxyless 與 OpenTelemetry 實現了一個完整的全鏈路泳道,并且無需借助 Envoy sidecar,就能基于 Isito 標準治理規(guī)則 Spec,來為 Kitex 設置對應的路由規(guī)則了。

當然,除了滿足 流量路由 能力之外,Kitex Proxyless 也在持續(xù)迭代優(yōu)化,滿足更多數據面治理能力需求。Proxyless 作為一種 ServiceMesh 數據面探索和實踐,除了能夠豐富網格數據面部署形態(tài)之外,也希望可以不斷打磨 Kitex,增強其在開源生態(tài)兼容方面的能力,打造一個開放包容的微服務生態(tài)體系。

5. 相關項目鏈接

下面是該案例涉及的項目清單:

  • biz-demo:https://github.com/cloudwego/biz-demo
  • kitex:https://github.com/cloudwego/kitex
  • hertz:https://github.com/cloudwego/hertz
  • kitex-xds:https://github.com/kitex-contrib/xds
  • kitex-opentelemetry:https://github.com/kitex-contrib/obs-opentelemetry
  • hertz-opentelemetry:https://github.com/hertz-contrib/obs-opentelemetry

該完整案例已提交在 biz-demo (https://github.com/cloudwego/biz-demo) 倉庫中,感興趣的同學可以前往查閱。

biz-demo 會包含一些基于 CloudWeGo 技術棧且具備一定業(yè)務場景的完整 Demo,初衷是能夠為企業(yè)用戶在生產中使用提供有價值的參考,非常歡迎更多同學能夠參與到 CloudWeGo 相關場景與案例的貢獻中來,一起來做一些有意思的嘗試。

責任編輯:龐桂玉 來源: 字節(jié)跳動技術團隊
相關推薦

2023-10-16 23:43:52

云原生可觀測性

2023-09-24 23:35:46

云原生Kubernetes

2021-11-18 10:01:00

Istio 全鏈路灰度微服務框架

2024-08-21 08:09:17

2022-08-07 21:59:57

高可用架構

2023-11-14 09:04:15

用戶節(jié)點不可用

2023-11-09 07:23:57

Istio路由分析

2023-01-30 22:34:44

Node.js前端

2016-12-13 08:45:48

2014-07-23 15:35:41

鏈路狀態(tài)

2024-01-05 00:29:36

全鏈路灰度發(fā)布云原生

2022-08-31 22:25:53

微服務架構DevOPs

2023-12-25 07:46:35

GatewayAPI開源

2021-11-01 08:16:26

模型Istio服務

2014-12-31 15:05:11

Android流量監(jiān)控

2022-12-28 09:07:41

2023-11-13 10:41:44

Spring微服務

2022-06-27 11:06:33

全鏈路影子庫影子表

2021-07-27 06:51:53

Istio 微服務Service Mes

2022-05-23 08:23:24

鏈路追蹤SleuthSpring
點贊
收藏

51CTO技術棧公眾號