基于WASM的無侵入式全鏈路A/B Test實(shí)踐

1 背景介紹

我們都知道,服務(wù)網(wǎng)格(ServiceMesh)可以為運(yùn)行其上的微服務(wù)提供無侵入式的流量治理能力。通過配置VirtualService和DestinationRule,即可實(shí)現(xiàn)流量管理、超時(shí)重試、流量復(fù)制、限流、熔斷等功能,而無需修改微服務(wù)代碼。

流量管理的前提是一個(gè)服務(wù)存在多個(gè)版本,我們可以按部署多版本的目的進(jìn)行分類,簡述如下以方便理解余文的目的。

  • traffic routing:根據(jù)請求信息(Header/Cookie/Query Params),將請求流量路由到指定服務(wù)(Service)的指定版本(Deployment)的端點(diǎn)上(Pod[])。就是我們所說的A/B測試(A/B Testing)。
  • traffic shifting:通過灰度/金絲雀(Canary)發(fā)布,將請求流量無差別地按比例路由到指定服務(wù)(Service)的各個(gè)版本(Deployment[])的端點(diǎn)上(Pod[])。
  • traffic switching/mirroring:通過藍(lán)綠(Blue/Green)發(fā)布,根據(jù)請求信息按比例進(jìn)行流量切換,以及進(jìn)行流量復(fù)制。

本文所述的實(shí)踐是根據(jù)請求Header實(shí)現(xiàn)全鏈路A/B測試。

1.1 功能簡述

從Istio社區(qū)的文檔,我們很容易找到關(guān)于如何根據(jù)請求Header將流量路由到一個(gè)服務(wù)的特定版本的文檔和示例。但是這個(gè)示例只能在全鏈路的第一個(gè)服務(wù)上生效。

舉例來說,一個(gè)請求要訪問A-B-C三個(gè)服務(wù),這三個(gè)服務(wù)都有en版本和fr版本。我們期待:

  • header值為user:en的請求,全鏈路路由為A1-B1-C1
  • header值為user:fr的請求,全鏈路路由為A2-B2-C2

相應(yīng)的VirtualService配置如下所示:

http:
- name: A|B|C-route
  match:
  - headers:
      user:
        exact: en
  route:
  - destination:
      host: A|B|C-svc
      subset: v1
- route:
  - destination:
      host: A|B|C-svc
      subset: v2

我們通過實(shí)測可以發(fā)現(xiàn),只有A這個(gè)服務(wù)的路由是符合我們預(yù)期的。B和C無法做到根據(jù)Header值路由到指定版本。

image.png

這是為什么呢?對于服務(wù)網(wǎng)格其上的微服務(wù)來說,這個(gè)header是憑空出現(xiàn)的,也就是微服務(wù)代碼無感知。因此,當(dāng)A服務(wù)請求B服務(wù)時(shí),不會透傳這個(gè)header;也就是說,當(dāng)A請求B時(shí),這個(gè)header已經(jīng)丟失了。這時(shí),這個(gè)匹配header進(jìn)行路由的VirtualService配置已經(jīng)毫無意義。

要解決這個(gè)問題,從微服務(wù)方的業(yè)務(wù)角度看,只能修改代碼(枚舉業(yè)務(wù)關(guān)注的全部header并透傳)。但這是一種侵入式的修改,而且無法靈活地支持新出現(xiàn)的header。

從服務(wù)網(wǎng)格的基礎(chǔ)設(shè)施角度看,任何header都是沒有業(yè)務(wù)意義且要被透傳的kv pair。只有做到這點(diǎn),服務(wù)網(wǎng)格才能實(shí)現(xiàn)無差別地透傳用戶自定義的header,從而支持無侵入式全鏈路A/B Test功能。

那么該怎樣實(shí)現(xiàn)呢?

1.2 社區(qū)現(xiàn)狀

前面已經(jīng)說明,在header無法透傳的情況下,單純地配置VirtualService的header匹配是無法實(shí)現(xiàn)這個(gè)功能的。

但是,在VirtualService中是否存在其他配置,可以實(shí)現(xiàn)header透傳呢?如果存在,那么單純使用VirtualService,代價(jià)是最小的。

經(jīng)過各種嘗試(包括精心配置header相關(guān)的set/add),我發(fā)現(xiàn)無法實(shí)現(xiàn)。原因是VirtualService對header的干預(yù)發(fā)生在inbound階段,而透傳是需要在outbound階段干預(yù)header的。而微服務(wù)workload沒有能力對憑空出現(xiàn)的header值進(jìn)行透傳,因此在路由到下一個(gè)服務(wù)時(shí),這個(gè)header就會丟失。

image.png

因此,我們可以得出一個(gè)結(jié)論:無法單純使用VirtualService實(shí)現(xiàn)無侵入式全鏈路A/B Test,進(jìn)一步地說,社區(qū)提供的現(xiàn)有配置都無法做到直接使用就能支持這個(gè)功能。

那么,就只剩下EnvoyFilter這個(gè)更高級的配置了。這是我們一開始很不希望的結(jié)論。原因有兩個(gè):

  1. EnvoyFilter的配置太過復(fù)雜,一般用戶很難在服務(wù)網(wǎng)格中快速學(xué)習(xí)和使用,即便我們提供示例,一旦需求稍有變化,示例對修改EnvoyFilter的參考價(jià)值甚微。
  2. 就算使用EnvoyFilter,目前Envoy內(nèi)置的filter也沒有直接支持這個(gè)功能的,需要借助Lua或者WebAssembly(WASM)進(jìn)行開發(fā)。

1.3 實(shí)現(xiàn)方案

接下來進(jìn)入技術(shù)選型。我用一句話來概括:

  • Lua的優(yōu)點(diǎn)是小巧,缺點(diǎn)是性能不理想
  • WASM的優(yōu)點(diǎn)是性能好,缺點(diǎn)是開發(fā)和分發(fā)相比Lua要困難。
  • WASM的實(shí)現(xiàn)主流是C++和Rust,其他語言的實(shí)現(xiàn)尚不成熟或者存在性能問題。本文使用的是Rust。

我們使用Rust開發(fā)一個(gè)WASM,在outbound階段,獲取用戶在EnvoyFilter中定義的header并向后傳遞。

WASM包的分發(fā)使用Kubernetes的configmap存儲,Pod通過annotation中的定義獲取WASM配置并加載。(為什么使用這種分發(fā)形式,后面會講。)

image.png

2 技術(shù)實(shí)現(xiàn)

本節(jié)所述的相關(guān)代碼:https://github.com/feuyeux/rust-wasm-4-envoy/tree/propaganda/propagate-headers-filter

2.1 使用RUST實(shí)現(xiàn)WASM

1 定義依賴

WASM工程的核心依賴crates只有一個(gè),就是proxy-wasm,這是使用Rust開發(fā)WASM的基礎(chǔ)包。此外,還有用于反序列化的包serde_json和用于打印日志的包log。Cargo.toml定義如下:

[dependencies]
proxy-wasm = "0.1.3"
serde_json = "1.0.62"
log = "0.4.14"

2 定義構(gòu)建

WASM的最終構(gòu)建形式是兼容c的動態(tài)鏈接庫,Cargo.toml定義如下:

[lib]
name = "propaganda_filter"
path = "src/propagate_headers.rs"
crate-type = ["cdylib"]

3 Header透傳功能

首先定義結(jié)構(gòu)體如下,head_tag_name是用戶自定義的header鍵的名稱,head_tag_value是對應(yīng)值的名稱。

struct PropagandaHeaderFilter {
    config: FilterConfig,
}

struct FilterConfig {
    head_tag_name: String,
    head_tag_value: String,
}

{proxy-wasm}/src/traits.rs中的trait HttpContext定義了on_http_request_headers方法。我們通過實(shí)現(xiàn)這個(gè)方法來完成Header透傳的功能。

impl HttpContext for PropagandaHeaderFilter {
    fn on_http_request_headers(&mut self, _: usize) -> Action {
        let head_tag_key = self.config.head_tag_name.as_str();
        info!("::::head_tag_key={}", head_tag_key);
        if !head_tag_key.is_empty() {
            self.set_http_request_header(head_tag_key, Some(self.config.head_tag_value.as_str()));
            self.clear_http_route_cache();
        }
        for (name, value) in &self.get_http_request_headers() {
            info!("::::H[{}] -> {}: {}", self.context_id, name, value);
        }
        Action::Continue
    }
}

第3-6行是獲取配置文件中用戶自定義的header鍵值對,如果存在就調(diào)用set_http_request_header方法,將鍵值對寫入當(dāng)前header。

第7行是對當(dāng)前proxy-wasm實(shí)現(xiàn)的一個(gè)workaround,如果你對此感興趣可以閱讀如下參考:

2.2 本地驗(yàn)證(基于Envoy)

1 WASM構(gòu)建

使用如下命令構(gòu)建WASM工程。需要強(qiáng)調(diào)的是wasm32-unknown-unknown這個(gè)target目前只存在于nightly中,因此在構(gòu)建之前需要臨時(shí)切換構(gòu)建環(huán)境。

rustup override set nightly
cargo build --target=wasm32-unknown-unknown --release

構(gòu)建完成后,我們在本地使用docker-compose啟動Envoy,對WASM功能進(jìn)行驗(yàn)證。

2 Envoy配置

本例需要為Envoy啟動提供兩個(gè)文件,一個(gè)是構(gòu)建好的propaganda_filter.wasm,一個(gè)是Envoy配置文件envoy-local-wasm.yaml。示意如下:

volumes:
  - ./config/envoy/envoy-local-wasm.yaml:/etc/envoy-local-wasm.yaml
  - ./target/wasm32-unknown-unknown/release/propaganda_filter.wasm:/etc/propaganda_filter.wasm

Envoy支持動態(tài)配置,本地測試采用靜態(tài)配置:

static_resources:
  listeners:
    - address:
        socket_address:
          address: 0.0.0.0
          port_value: 80
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
...
                http_filters:
                  - name: envoy.filters.http.wasm
                    typed_config:
                      "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                      type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
                      value:
                        config:
                          name: "header_filter"
                          root_id: "propaganda_filter"
                          configuration:
                            "@type": "type.googleapis.com/google.protobuf.StringValue"
                            value: |
                              {
                                "head_tag_name": "custom-version",
                                "head_tag_value": "hello1-v1"
                              }
                          vm_config:
                            runtime: "envoy.wasm.runtime.v8"
                            vm_id: "header_filter_vm"
                            code:
                              local:
                                filename: "/etc/propaganda_filter.wasm"
                            allow_precompiled: true
...

Envoy的配置重點(diǎn)關(guān)注如下3點(diǎn):

  • 15行 我們在http_filters中定義了一個(gè)名稱為header_filtertype.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
  • 32行 本地文件路徑為/etc/propaganda_filter.wasm
  • 20-26行 相關(guān)配置的類型是type.googleapis.com/google.protobuf.StringValue,值的內(nèi)容是{"head_tag_name": "custom-version","head_tag_value": "hello1-v1"}。這里自定義的Header鍵名為custom-version,值為hello1-v1。

3 本地驗(yàn)證

執(zhí)行如下命令啟動docker conpomse:

docker-compose up --build

請求本地服務(wù):

curl -H "version-tag":"v1" "localhost:18000"

此時(shí)Envoy的日志應(yīng)有如下輸出:

proxy_1        | [2021-02-25 06:30:09.217][33][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1152] wasm log: ::::create_http_context head_tag_name=custom-version,head_tag_value=hello1-v1
proxy_1        | [2021-02-25 06:30:09.217][33][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1152] wasm log: ::::head_tag_key=custom-version
...
proxy_1        | [2021-02-25 06:30:09.217][33][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1152] wasm log: ::::H[2] -> custom-version: hello1-v1

2.3 WASM的分發(fā)方式

WASM的分發(fā)是指將WASM包存儲于一個(gè)分布式倉庫中,供指定的Pod拉取的過程。

1 solo的wasme框架

solo提供了一整套WASM的開發(fā)框架wasme,基于該框架可以開發(fā)-構(gòu)建-分發(fā)WASM包(OCI image)并部署到

Webassembly Hub。同時(shí),該框架以CRD的形式對EnvoyFilter進(jìn)行了封裝,且可以讓相關(guān)Pod從Webassembly Hub拉取WASM包。

image.png

這個(gè)方案的優(yōu)點(diǎn)很明顯,完整地支持了WASM的開發(fā)到上線的生命周期。但這個(gè)方案的缺點(diǎn)也非常明顯,wasme的自包含導(dǎo)致了很難將其拆分,并擴(kuò)展到solo體系之外。

wasme的方向是正確的,比如通過CRD來封裝EnvoyFilter以及Webassembly Hub這種WASM中央倉庫的思路。我的觀點(diǎn)是,各大廠商順著這個(gè)思路發(fā)展下去,提供成熟的定制和插拔能力后,WASM分發(fā)的終態(tài)就會浮出水面。

2 Envoy的remote方式

Envoy同時(shí)支持localremote形式的資源定義。對比如下:

vm_config:
  runtime: "envoy.wasm.runtime.v8"
  vm_id: "header_filter_vm"
  code:
    local:
      filename: "/etc/propaganda_filter.wasm"
vm_config:
  runtime: "envoy.wasm.runtime.v8"
  code:
    remote:
      http_uri:
        uri: "http://*.*.*.216:8000/propaganda_filter.wasm"
        cluster: web_service
        timeout:
          seconds: 60
      sha256: "da2e22*"

remote方式是最接近原始Enovy的,因此這種方式本來是本例的首選。但是實(shí)測過程中發(fā)現(xiàn)在包的hash校驗(yàn)上存在問題,詳見下方參考。并且,Envoy社區(qū)的大牛周禮贊反饋我說remote不是Envoy支持WASM分發(fā)的未來方向。因此,本例最終放棄這種方式。

3 Configmap+Envoy的local方式

雖然這種方式不是WASM分發(fā)的終態(tài),但是本例最終選擇了這個(gè)方案。雖然configmap的本職工作不是存WASM的,但是configmap和Envoy的local模式都很成熟,兩者結(jié)合恰能滿足當(dāng)前需求。

要把WASM包塞到配置中,首要考慮的是包的尺寸。我們使用wasm-gc進(jìn)行包裁剪,示意如下:

ls -hl target/wasm32-unknown-unknown/release/propaganda_filter.wasm
wasm-gc ./target/wasm32-unknown-unknown/release/propaganda_filter.wasm ./target/wasm32-unknown-unknown/release/propaganda-header-filter.wasm
ls -hl target/wasm32-unknown-unknown/release/propaganda-header-filter.wasm

執(zhí)行結(jié)果如下,可以看到裁剪前后,包的尺寸對比:

-rwxr-xr-x  2 han  staff   1.7M Feb 25 15:38 target/wasm32-unknown-unknown/release/propaganda_filter.wasm
-rw-r--r--  1 han  staff   136K Feb 25 15:38 target/wasm32-unknown-unknown/release/propaganda-header-filter.wasm

創(chuàng)建configmap:

wasm_image=target/wasm32-unknown-unknown/release/propaganda-header-filter.wasm
kubectl -n $NS create configmap -n $NS propaganda-header --from-file=$wasm_image

為指定Deployment打Patch:

patch_annotations=$(cat config/annotations/patch-annotations.yaml)
kubectl -n $NS patch deployment "hello$i-deploy-v$j" -p "$patch_annotations"

patch-annotations.yaml如下:

spec:
  template:
    metadata:
      annotations:
        sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","configMap": {"name":"propaganda-header"}}]'
        sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'

2.4 集群驗(yàn)證(基于Istio)

1 實(shí)驗(yàn)示例

WASM分發(fā)到Kubernetes的configmap后,我們可以進(jìn)行集群驗(yàn)證了。示例(源代碼)包含3個(gè)Service:hello1-hello2-hello3,每個(gè)服務(wù)包含2個(gè)版本:v1/env2/fr。

每個(gè)Service配置了VirtualService和DestinationRule用來定義匹配Header并路由到指定版本。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: hello2-vs
spec:
  hosts:
    - hello2-svc
  http:
  - name: hello2-v2-route
    match:
    - headers:
        route-v:
          exact: hello2v2
    route:
    - destination:
        host: hello2-svc
        subset: hello2v2
  - route:
    - destination:
        host: hello2-svc
        subset: hello2v1
----
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: hello2-dr
spec:
  host: hello2-svc
  subsets:
    - name: hello2v1
      labels:
        version: v1
    - name: hello2v2
      labels:
        version: v2

Envoyfilter示意如下:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: hello1v2-propaganda-filter
spec:
  workloadSelector:
    labels:
      app: hello1-deploy-v2
      version: v2
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_OUTBOUND
        proxy:
          proxyVersion: "^1\\.8\\.*"
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
              subFilter:
                name: envoy.filters.http.router
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.wasm
          typed_config:
            "@type": type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
            value:
              config:
                name: propaganda_filter
                root_id: propaganda_filter_root
                configuration:
                  '@type': type.googleapis.com/google.protobuf.StringValue
                  value: |
                    {
                      "head_tag_name": "route-v",
                      "head_tag_value": "hello2v2"
                    }
                vm_config:
                  runtime: envoy.wasm.runtime.v8
                  vm_id: propaganda_filter_vm
                  code:
                    local:
                      filename: /var/local/lib/wasm-filters/propaganda-header-filter.wasm
                  allow_precompiled: true

2 驗(yàn)證方法

攜帶header的請求curl -H "version:v1" "http://$ingressGatewayIp:8001/hello/xxx"通過istio-ingressgateway進(jìn)入,全鏈路按header值,進(jìn)入服務(wù)的指定版本。這里,由于header中指定了versionv2,那么全鏈路將
hello1 v2-hello2 v2-hello3 v2。效果如下圖所示。

image.png

驗(yàn)證過程和結(jié)果示意如下。

for i in {1..5}; do
    curl -s -H "route-v:v2" "http://$ingressGatewayIp:$PORT/hello/eric" >>result
    echo >>result
done
check=$(grep -o "Bonjour eric" result | wc -l)
if [[ "$check" -eq "15" ]]; then
    echo "pass"
else
    echo "fail"
    exit 1
fi
Bonjour eric@hello1:172.17.68.205<Bonjour eric@hello2:172.17.68.206<Bonjour eric@hello3:172.17.68.182
Bonjour eric@hello1:172.17.68.205<Bonjour eric@hello2:172.17.68.206<Bonjour eric@hello3:172.17.68.182
Bonjour eric@hello1:172.17.68.205<Bonjour eric@hello2:172.17.68.206<Bonjour eric@hello3:172.17.68.182
Bonjour eric@hello1:172.17.68.205<Bonjour eric@hello2:172.17.68.206<Bonjour eric@hello3:172.17.68.182
Bonjour eric@hello1:172.17.68.205<Bonjour eric@hello2:172.17.68.206<Bonjour eric@hello3:172.17.68.182

我們看到,輸出信息Bonjour eric來自各個(gè)服務(wù)的fr版本,說明功能驗(yàn)證通過。

3 性能分析

新增EnvoyFilter+WASM后,功能驗(yàn)證通過,但這會帶來多少延遲開銷呢?這是服務(wù)網(wǎng)格的提供者和使用者都非常關(guān)心的問題。本節(jié)將對如下兩個(gè)關(guān)注點(diǎn)進(jìn)行驗(yàn)證。

  • 增加EnvoyFilter+WASM后的增量延遲開銷情況
  • WASM版本和Lua版本的開銷對比

3.1 Lua實(shí)現(xiàn)

Lua的實(shí)現(xiàn)可以直接寫到EnvoyFilter中,無需獨(dú)立的工程。示例如下:

patch:
  operation: INSERT_BEFORE
  value:
    name: envoy.lua
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
      inlineCode: |
        function envoy_on_request(handle)
          handle:logInfo("[propagate header] route-v:hello3v2")
          handle:headers():add("route-v", "hello3v2")
        end

3.2 壓測方法

1 部署

  • 分別在3個(gè)namespace上部署相同的Deployment/Service/VirtualService/DestinationRule
  • hello-abtest-lua中部署基于Lua的EnvoyFilter
  • hello-abtest-wasm中部署基于WASM的EnvoyFilter
hello-abtest        基準(zhǔn)環(huán)境
hello-abtest-lua    增加EnvoyFilter+LUA的環(huán)境
hello-abtest-wasm   增加EnvoyFilter+WASM的環(huán)境

2 工具

本例使用hey作為壓測工具。hey前身是boom,用來代替ab(Apache Bench)。使用相同的壓測參數(shù)分別對三個(gè)環(huán)境進(jìn)行壓測。示意如下:

# 并發(fā)work數(shù)量
export NUM=2000
# 每秒請求數(shù)量
export QPS=2000
# 壓測執(zhí)行時(shí)常
export Duration=10s

hey -c $NUM -q $QPS -z $Duration -H "route-v:v2" http://$ingressGatewayIp:$PORT/hello/eric > $SIDECAR_WASM_RESULT

請關(guān)注hey壓測結(jié)果文件,結(jié)果最后不能出現(xiàn)socket: too many open files,否則影響結(jié)果??梢允褂?code>ulimit -n $MAX_OPENFILE_NUM命令配置,然后再調(diào)整壓測參數(shù),以確保結(jié)果的準(zhǔn)確性。

3.3 報(bào)告

我們從三份結(jié)果報(bào)告中選取4個(gè)關(guān)鍵指標(biāo),如下圖所示:

image.png
基準(zhǔn) WASM LUA
1000并發(fā)1000QPS持續(xù)10秒鐘
平均延遲 0.6317 secs 0.6395 secs 0.7012 secs
延遲99%分布 0.9167 secs 0.9352 secs 1.1355 secs
QPS 1541 1519 1390
Total 16281 16109 1390
2000并發(fā)2000QPS持續(xù)10秒鐘
平均延遲 1.2078 secs 1.3290 secs 1.4593 secs
延遲99%分布 1.8621 secs 1.8354 secs 2.2116 secs
QPS 1564 1421 1290
Total 17622 16009 14662

3.4 結(jié)論

  1. 相對于基準(zhǔn)版本,增加EnvoyFilter的兩個(gè)版本,平均延遲多出幾十個(gè)到幾百個(gè)毫秒,增加耗時(shí)比為
  • wasm 1.2% (0.6395-0.6317)/0.63171% (1.3290-1.2078)/1.2078
  • lua 11%(0.7012-0.6317)/0.631720% (1.4593-1.2078)/1.2078
  1. WASM版本的性能明顯優(yōu)于LUA版本

注:相比LUA版本,WASM的實(shí)現(xiàn)是一套代碼多份配置。因此WASM的執(zhí)行過程還比LUA多出一個(gè)獲取配置變量的過程。

4 展望

4.1 如何使用

本文從技術(shù)實(shí)現(xiàn)角度,講述了如何實(shí)現(xiàn)并驗(yàn)證一個(gè)透傳用戶自定義Header的WASM,從而支持無侵入式全鏈路A/B Test這個(gè)需求。

但是,作為服務(wù)網(wǎng)格的使用者,如果按照本文一步步去實(shí)現(xiàn),是非常繁瑣且容易出錯(cuò)的。

服務(wù)網(wǎng)格的提供者應(yīng)當(dāng)提供一種類似solo wasme的方式,將功能所需的配置進(jìn)行封裝,并發(fā)布到插件目錄。用戶只需在插件目錄中選擇插件,并為插件提供自定義的Header等極少數(shù)量的kv配置,即可自動生成和部署相關(guān)的EnvoyFilter+WASM+VirtualService+DestinationRule。

4.2 如何擴(kuò)展

本例只展示了基于Header的匹配路由功能,如果我們希望根據(jù)Query Params進(jìn)行匹配和路由該如何擴(kuò)展呢?

一種方式是開發(fā)并替換本例中的WASM,一種方式是由服務(wù)網(wǎng)格的提供者發(fā)布更多的插件目錄。前者更靈活,但非托管無法保證穩(wěn)定性和兼容性;后者更健壯,但會有滯后。

以上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容