透過無 Proxy gRPC 服務設定進階流量管理
這項設定適用於預先發布版客戶,但我們不建議新 Cloud Service Mesh 使用者採用。詳情請參閱 Cloud Service Mesh 服務路由總覽。
本文提供使用下列流量管理功能設定 Cloud Service Mesh 的操作說明:
- 路線比對
- 流量拆分
- 斷路機制
- 錯誤植入
- 串流時間長度上限
- 重試
- 工作階段相依性
- 離群值偵測
- 地區負載平衡
雖然本文著重於說明如何在 Compute Engine 上使用無 Proxy gRPC 設定進階流量管理,但在 Google Kubernetes Engine (GKE) 上使用無 Proxy gRPC 時,也支援進階流量管理。
事前準備
設定進階流量管理之前,請先參閱「準備使用無 Proxy gRPC 服務設定 Cloud Service Mesh」一文中的相關規定。除非符合所有規定,否則您無法設定進階流量管理。
如要瞭解這些功能的概念資訊,請參閱「進階流量管理」。
關於 gRPC 錢包範例
為了說明這些功能,您將部署 gRPC Wallet 範例。在本例中,有三個 gRPC 服務 (grpc.examples.wallet.Wallet
、grpc.examples.wallet.stats.Stats
和 grpc.examples.wallet.account.Account
) 會部署為三個個別應用程式。
如以下圖表所示,您會建立 gRPC 用戶端,用來呼叫 Wallet
服務,取得帳戶餘額,並呼叫 Stats
服務,取得代幣價格。Wallet
服務會呼叫 Stats
和 Account
服務來計算餘額。Stats
服務也會呼叫 Account
服務來取得使用者資訊。
在本例中,您會部署兩個版本的 Wallet
和 Stats
實作項目,以便說明根據您設定的規則進行要求轉送。如要模擬建構及部署不同版本的服務,您可以使用伺服器標記來變更僅建構一次的二進位檔行為。
--port
旗標會指定 VM 執行個體上的服務所監聽的通訊埠。--hostname_suffix
旗標會指定要附加至回應要求的 VM 執行個體主機名稱的值。產生的值會新增為回應中的hostname
中繼資料。這有助您找出執行個體群組中哪個執行個體回應了用戶端要求。- 值為
true
的--premium_only
旗標會指定該服務為stats
服務的進階版。 - 值為
true
的--v1_behavior
標記會指定錢包二進位檔的行為為 v1 版本。
下表列出執行 gRPC 服務的每個 VM 執行個體的這些標記值、執行個體群組中的執行個體數量,以及這些執行個體群組所屬的後端服務。
後端服務 | 執行個體群組 | 執行個體 | 伺服器旗標 |
---|---|---|---|
account |
account |
2 | --port=50053 --hostname_suffix="account"
|
stats |
stats |
2 | --port=50052 --hostname_suffix="stats" --account_server="xds:///account.grpcwallet.io"
|
stats-premium |
stats-premium |
2 | --port=50052 --hostname_suffix="stats_premium" --account_server="xds:///account.grpcwallet.io" --premium_only=true
|
wallet-v1 wallet-v1-affinity
|
wallet-v1 |
2 | --port=50051 --hostname_suffix="wallet_v1" --v1_behavior=true --account_server="xds:///account.grpcwallet.io" --stats_server="xds:///stats.grpcwallet.io"
|
wallet-v2 |
wallet-v2 |
1 | --port=50051 --hostname_suffix "wallet_v2" --account_server="xds:///account.grpcwallet.io" --stats_server="xds:///stats.grpcwallet.io"
|
部署這些服務後,您可以根據下表中的轉送規則,設定 Cloud Service Mesh 將來自測試用戶端的請求轉送至這些後端服務。用戶端會連線至服務的虛擬主機名稱,如「Host」欄所示。
主機 | 比對規則 | 轉送動作 |
---|---|---|
wallet.grpcwallet.io |
路徑前置字元:"/" 標頭是否存在: "session_id"
|
前往wallet-v1-affinity 的路線 |
路徑前置字串:"/" 標頭: {"route": "timeout"}
|
設定 5 秒的逾時時間,並將 路由至 wallet-v2 |
|
路徑前置字串:"/" 標頭: {"route": "fault"}
|
讓 50% 的要求失敗,並將其餘的要求轉送至 wallet-v2
|
|
路徑前置字串:"/" 標頭: {"membership": "premium"}
|
路由至 wallet-v1 和 失敗時最多重試 3 次 |
|
完整路徑:/grpc.examples.wallet.Wallet/FetchBalance |
路線:wallet-v1 :70%wallet-v2 :30%
|
|
預設 | 前往wallet-v1 的路線 |
|
stats.grpcwallet.io |
路徑前置字串:"/" 標頭: {"membership": "premium"}
|
前往stats-premium 的路線 |
預設 | 前往stats 的路線 |
|
account.grpcwallet.io |
路徑前置字串:"/" 標頭: {"route": "account-fault"}
|
讓 30% 的要求失敗,並將其餘的要求導向 account
|
預設 | account |
這個範例會將流量以 70/30 的比例分配給兩項現有服務。如果您要將流量切割給網址對應未曾參照的新服務,請先將新服務新增至 weightedBackendServices
,並為其指定 0
的權重。然後逐步提高指派給該服務的權重。
測試用戶端提供下列選項,可讓您產生適當的要求,以示範流量管理功能。
選項 | 說明 |
---|---|
--watch=true |
呼叫串流方法來監控餘額/價格 |
--unary_watch=true |
重複呼叫一元方法來監控餘額/價格 |
--user=Alice |
插入標頭 {"membership": "premium"} |
--user=Bob |
插入標頭 {"membership": "normal"} |
--route=value |
插入標頭 {"route": "value"} |
--affinity=true |
插入標頭 {"session_id": "value"} |
準備本機環境
如要為這些範例設定本機環境,請執行下列指令:
更新
gcloud
二進位檔,確保您使用的是最新版本:gcloud components update
下載範例存放區:
sudo apt-get install git -y
複製範例的正確存放區:
export EXAMPLES_VERSION=v1.1.x git clone -b $EXAMPLES_VERSION --single-branch --depth=1 \ https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git
建立及設定 Cloud Router 執行個體
在本節中,您將在各個區域中建立 Cloud Router 執行個體,並為 Cloud NAT 設定這些執行個體。本範例建立的 VM 沒有外部 IP 位址,但需要有網際網路存取權。使用 Cloud NAT 設定 Cloud Router 可提供必要的存取權。
gcloud
建立 Cloud Router 執行個體:
gcloud compute routers create nat-router-us-central1 \ --network=default \ --region=us-central1
為 Cloud NAT 設定路由器:
gcloud compute routers nats create nat-config \ --router-region=us-central1 \ --router=nat-router-us-central1 \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips
建立 gRPC 健康狀態檢查和防火牆規則
在本節中,您將建立 gRPC 健康狀態檢查和防火牆規則,允許 gRPC 健康狀態檢查要求存取網路。稍後,gRPC 健康狀態檢查會與後端服務建立關聯,以便檢查這些後端服務的後端執行個體健康狀態。
gcloud
建立健康狀態檢查:
gcloud compute health-checks create grpc grpcwallet-health-check \ --use-serving-port
建立健康狀態檢查的防火牆規則:
gcloud compute firewall-rules create grpcwallet-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags allow-health-checks \ --rules tcp:50051-50053
建立執行個體範本
在本節中,您將建立執行個體範本,以便部署在 50053
通訊埠上公開的 account
gRPC 服務。
gcloud
建立執行個體範本:
gcloud compute instance-templates create grpcwallet-account-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=allow-health-checks \ --network-interface=no-address \ --image-family=debian-10 \ --image-project=debian-cloud \ --metadata-from-file=startup-script=<(echo "#! /bin/bash set -ex cd /root export HOME=/root sudo apt-get update -y pushd \$(mktemp -d) sudo apt-get install -y wget git wget https://dl.google.com/go/go1.16.5.linux-amd64.tar.gz sudo tar -C /usr/local -xvf go1.16.5.linux-amd64.tar.gz sudo cp /usr/local/go/bin/go /usr/bin/go popd git clone -b $EXAMPLES_VERSION --single-branch --depth=1 https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git cd traffic-director-grpc-examples/go/account_server/ go build . sudo systemd-run ./account_server --port 50053 --hostname_suffix account")
建立代管執行個體群組
代管執行個體群組 (MIG) 會使用自動調度資源,視需要建立新的 VM 執行個體。在本節中,您將使用先前建立的執行個體範本,建立 MIG。
gcloud
建立執行個體群組:
gcloud compute instance-groups managed create grpcwallet-account-mig-us-central1 \ --zone=us-central1-a \ --size=2 \ --template=grpcwallet-account-template
設定具名通訊埠
在本節中,您將為 gRPC 服務設定命名通訊埠。命名的通訊埠是 gRPC 服務用來監聽要求的通訊埠。在這個範例中,已命名的通訊埠是 50053
。
gcloud
建立命名通訊埠:
gcloud compute instance-groups set-named-ports grpcwallet-account-mig-us-central1 \ --named-ports=grpcwallet-account-port:50053 \ --zone=us-central1-a
建立後端服務
在本節中,您將使用 INTERNAL_SELF_MANAGED
的負載平衡機制和 GRPC
通訊協定,建立全球後端服務。接著,您可以將健康狀態檢查和執行個體群組與後端服務建立關聯。在本例中,您會使用在「建立代管執行個體群組」一節中建立的 MIG。這個 MIG 會執行 account
gRPC 服務。--port-name
標記中的通訊埠是您在「設定命名通訊埠」中建立的命名通訊埠。
gcloud
建立後端服務,然後將健康狀態檢查與新的後端服務建立關聯:
gcloud compute backend-services create grpcwallet-account-service \ --global \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=GRPC \ --port-name=grpcwallet-account-port \ --health-checks=grpcwallet-health-check
將代管執行個體群組新增為後端:
gcloud compute backend-services add-backend grpcwallet-account-service \ --instance-group=grpcwallet-account-mig-us-central1 \ --instance-group-zone=us-central1-a \ --global
建立 gRPC Wallet 範例中使用的其他後端服務的步驟與前述步驟類似。您可以執行殼層指令碼來建立其餘的服務。指令碼會部署下列後端服務:
stats
stats-premium
wallet-v1
wallet-v1-affinity
wallet-v2
執行建立額外後端服務的殼層指令碼:
traffic-director-grpc-examples/scripts/create_service.sh go stats 50052 stats '--account_server="xds:///account.grpcwallet.io"' traffic-director-grpc-examples/scripts/create_service.sh go stats 50052 stats-premium '--account_server="xds:///account.grpcwallet.io" --premium_only=true' # This command creates wallet-v1 and wallet-v1-affinity backend services. traffic-director-grpc-examples/scripts/create_service.sh java wallet 50051 wallet-v1 '--account_server="xds:///account.grpcwallet.io" --stats_server="xds:///stats.grpcwallet.io" --v1_behavior=true' traffic-director-grpc-examples/scripts/create_service.sh java wallet 50051 wallet-v2 '--account_server="xds:///account.grpcwallet.io" --stats_server="xds:///stats.grpcwallet.io"'
建立轉送規則
在本節中,您將建立網址對應,用於示範各種流量管理功能。網址對應會指定本範例中服務的虛擬主機名稱和相關轉送規則。詳情請參閱「轉送規則對應」。
在網址對應中,hostRules
會指定範例中服務的虛擬主機名稱。這是用戶端在管道 URI 中使用的名稱,用於連線至特定服務。舉例來說,如要向 account
服務傳送要求,用戶端會在管道 URI 中使用 xds:///account.grpcwallet.io
。在 hostRules
中,設定 hosts
項目,並將值設為 account.grpcwallet.io
。
與 hosts
項目相關聯的 pathMatcher
會指定 pathMatcher
的名稱,其中包含該虛擬主機的所有轉送規則。pathMatcher
設定包含相符規則和對應的動作規則,如「關於 gRPC Wallet 範例」一文所述。
gcloud
建立網址對應:
export PROJECT_ID=$(gcloud config list --format 'value(core.project)') export BS_PREFIX=projects/$PROJECT_ID/global/backendServices/grpcwallet gcloud compute url-maps import grpcwallet-url-map << EOF name: grpcwallet-url-map defaultService: $BS_PREFIX-account-service hostRules: - hosts: - account.grpcwallet.io pathMatcher: grpcwallet-account-path-matcher - hosts: - stats.grpcwallet.io pathMatcher: grpcwallet-stats-path-matcher - hosts: - wallet.grpcwallet.io pathMatcher: grpcwallet-wallet-path-matcher pathMatchers: - name: grpcwallet-account-path-matcher defaultService: $BS_PREFIX-account-service routeRules: - matchRules: - prefixMatch: / headerMatches: - headerName: route exactMatch: account-fault priority: 0 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-account-service weight: 100 faultInjectionPolicy: abort: httpStatus: 503 percentage: 30 - name: grpcwallet-stats-path-matcher defaultService: $BS_PREFIX-stats-service routeRules: - matchRules: - prefixMatch: / headerMatches: - headerName: membership exactMatch: premium priority: 0 service: $BS_PREFIX-stats-premium-service - name: grpcwallet-wallet-path-matcher defaultService: $BS_PREFIX-wallet-v1-service routeRules: - matchRules: - prefixMatch: / headerMatches: - headerName: session_id presentMatch: true priority: 0 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v1-affinity-service weight: 100 - matchRules: - prefixMatch: / headerMatches: - headerName: route exactMatch: timeout priority: 1 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v2-service weight: 100 maxStreamDuration: seconds: 5 - matchRules: - prefixMatch: / headerMatches: - headerName: route exactMatch: fault priority: 2 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v2-service weight: 100 faultInjectionPolicy: abort: httpStatus: 503 percentage: 50 - matchRules: - prefixMatch: / headerMatches: - headerName: membership exactMatch: premium priority: 3 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v1-service weight: 100 retryPolicy: retryConditions: - unavailable numRetries: 3 - matchRules: - fullPathMatch: /grpc.examples.wallet.Wallet/FetchBalance priority: 4 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v1-service weight: 70 - backendService: $BS_PREFIX-wallet-v2-service weight: 30 - matchRules: - prefixMatch: /grpc.examples.wallet.Wallet/ priority: 5 routeAction: weightedBackendServices: - backendService: $BS_PREFIX-wallet-v2-service weight: 100 EOF
建立目標 Proxy 和轉送規則
在本節中,您將建立目標 gRPC Proxy 和轉送規則。
目標 gRPC 代理程式會參照您在上一個步驟中建立的網址對應項目。旗標 --validate-for-proxyless
會啟用設定檢查,避免您不小心啟用與無 Proxy gRPC 部署項目不相容的功能。
gcloud
建立目標 gRPC Proxy:
gcloud compute target-grpc-proxies create grpcwallet-proxy \ --url-map=grpcwallet-url-map \ --validate-for-proxyless
轉送規則會參照您建立的目標 gRPC Proxy。負載平衡架構設為 INTERNAL_SELF_MANAGED
,表示 Cloud Service Mesh 會使用這個轉送規則。必須是通用轉送規則。IP 位址會設為 0.0.0.0
,因為無 Proxy 的 gRPC 用戶端會透過傳送 LDS 要求至 Cloud Service Mesh,而非執行 DNS 查詢,來解析目標 URI 中的 hostname:port
。詳情請參閱「名稱解析配置方案」。
如果目標 URI 未指定通訊埠,預設值為 80
。舉例來說,目標 URI xds:///foo.myservice:8080
會比對使用通訊埠 8080
設定的轉送規則。在這個範例中,轉送規則是使用通訊埠 80
設定。
gcloud
建立轉送規則:
gcloud compute forwarding-rules create grpcwallet-forwarding-rule \ --global \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --address=0.0.0.0 \ --address-region=us-central1 \ --target-grpc-proxy=grpcwallet-proxy \ --ports=80 \ --network=default
驗證設定
設定程序完成後,請查看 Google Cloud 控制台的 Cloud Service Mesh 頁面,確認您設定的後端服務是否可用。確認後端服務和相關後端的健康狀態為正常。應該會在幾分鐘內完成。
驗證轉送配置
在本節中,您將驗證轉送設定是否正常運作。您可以使用 grpcurl
工具測試設定。
gcloud
建立用戶端 VM,並在其中執行用戶端來測試服務。您可以選擇加入
--network-interface=no-address
標記。gcloud compute instances create grpc-wallet-client \ --zone=us-central1-a \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --image-family=debian-10 \ --image-project=debian-cloud \ --metadata-from-file=startup-script=<(echo '#! /bin/bash set -e export GRPC_XDS_BOOTSTRAP=/run/td-grpc-bootstrap.json # Expose bootstrap variable to SSH connections echo export GRPC_XDS_BOOTSTRAP=$GRPC_XDS_BOOTSTRAP | sudo tee /etc/profile.d/grpc-xds-bootstrap.sh # Create the bootstrap file curl -L https://storage.googleapis.com/traffic-director/td-grpc-bootstrap-0.16.0.tar.gz | tar -xz ./td-grpc-bootstrap-0.16.0/td-grpc-bootstrap | sudo tee $GRPC_XDS_BOOTSTRAP')
使用 SSH 存取 VM,並執行下列指令來準備 VM:
export EXAMPLES_VERSION=v1.1.x sudo apt-get update sudo apt-get install git -y
執行下列指令:
git clone -b $EXAMPLES_VERSION --single-branch --depth=1 \ https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.6.1/grpcurl_1.6.1_linux_x86_64.tar.gz | tar -xz chmod +x grpcurl
如要使用無附加 Proxy 的服務,gRPC 用戶端必須使用 xds
名稱解析配置。這個配置會告知用戶端使用的 gRPC 程式庫,使用 xDS 伺服器解析主機名稱。如要執行此操作,您必須設定引導程序。
上一節中的啟動指令碼會設定 GRPC_XDS_BOOTSTRAP
環境變數,並使用輔助指令碼產生引導檔案。產生的啟動檔案中 TRAFFICDIRECTOR_GCP_PROJECT_NUMBER
、TRAFFICDIRECTOR_NETWORK_NAME
和區域的值,是從瞭解 Compute Engine VM 執行個體這些詳細資料的中繼資料伺服器取得。您可以使用 -gcp-project-number
和 -vpc-network-name
選項,手動將這些值提供給輔助程式。
使用 grpcurl
工具驗證設定
在 SSH 殼層中執行下列指令,確認 wallet-service
、stats-service
和 account-service
是否正在執行:
./grpcurl -plaintext xds:///account.grpcwallet.io list ./grpcurl -plaintext -d '{"token": "2bd806c9"}' xds:///account.grpcwallet.io grpc.examples.wallet.account.Account/GetUserInfo ./grpcurl -plaintext -H 'authorization:2bd806c9' -H 'membership:premium' xds:///stats.grpcwallet.io grpc.examples.wallet.stats.Stats/FetchPrice ./grpcurl -plaintext -H 'authorization:2bd806c9' -H 'membership:premium' -d '{"include_balance_per_address": true}' xds:///wallet.grpcwallet.io grpc.examples.wallet.Wallet/FetchBalance
您會看到下列結果:
grpc.examples.wallet.account.Account grpc.health.v1.Health grpc.reflection.v1alpha.ServerReflection { "name": "Alice", "membership": "PREMIUM" } { "price": "10295" } { "balance": "5089953" }
透過 grpc-wallet
客戶驗證
請按照下列語言專屬操作說明驗證設定。這些指令會傳送多個 RPC,其中有些會附加額外中繼資料,以顯示要求是根據網址對應的配對規則轉送至後端服務。這項指令也會為每個回應列印 VM 執行個體的主機名稱,顯示要求已路由至哪個 VM 執行個體。
Java
如要使用 gRPC Java 用戶端驗證服務,請執行下列指令:
sudo apt-get install -y openjdk-11-jdk-headless
執行下列指令:
cd ~/traffic-director-grpc-examples/java ./gradlew installDist # This command calls 'FetchBalance' from 'wallet-service' in a loop, # to demonstrate that 'FetchBalance' gets responses from 'wallet-v1' (70%) # and 'wallet-v2' (30%). ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob # This command calls the streaming RPC 'WatchBalance' from 'wallet-service'. # The RPC path matches the service prefix, so all requests are # sent to 'wallet-v2'. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob # This command calls 'WatchPrice' from 'stats-service'. It sends the # user's membership (premium or not) in metadata. Premium requests are # all sent to 'stats-premium' and get faster responses. Alice's requests # always go to premium and Bob's go to regular. ./build/install/wallet/bin/client price --stats_server="xds:///stats.grpcwallet.io" --watch=true --user=Bob ./build/install/wallet/bin/client price --stats_server="xds:///stats.grpcwallet.io" --watch=true --user=Alice
Go
如要使用 gRPC Go 用戶端驗證服務,請安裝 golang 或按照官方操作說明操作:
sudo apt-get install -y wget wget https://dl.google.com/go/go1.16.5.linux-amd64.tar.gz sudo tar -C /usr/local -xvf go1.16.5.linux-amd64.tar.gz sudo ln -s /usr/local/go/bin/go /usr/bin/go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client go build # This command calls 'FetchBalance' from 'wallet-service' in a loop, # to demonstrate that 'FetchBalance' gets responses from 'wallet-v1' (70%) # and 'wallet-v2' (30%). ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch --user=Bob # This command calls the streaming RPC 'WatchBalance' from 'wallet-service'. # The RPC path matches the service prefix, so all requests # are sent to 'wallet-v2'. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob # This command calls 'WatchPrice' from 'stats-service'. It sends the # user's membership (premium or not) in metadata. Premium requests are # all sent to 'stats-premium' and get faster responses. Alice's requests # always go to premium and Bob's go to regular. ./wallet_client price --stats_server="xds:///stats.grpcwallet.io" --watch --user=Bob ./wallet_client price --stats_server="xds:///stats.grpcwallet.io" --watch --user=Alice
C++
如要使用 gRPC C++ 用戶端驗證服務,請執行下列指令:
sudo apt-get install -y build-essential
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp ../tools/bazel build :client # This command calls 'FetchBalance' from 'wallet-service' in a loop, # to demonstrate that 'FetchBalance' gets responses from 'wallet-v1' (70%) # and 'wallet-v2' (30%). ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob # This command calls the streaming RPC 'WatchBalance' from 'wallet-service'. # The RPC path matches the service prefix, so all requests are sent to 'wallet-v2'. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob # This command calls 'WatchPrice' from 'stats-service'. It sends the # user's membership (premium or not) in metadata. Premium requests are # all sent to 'stats-premium' and get faster responses. Alice's requests # always go to premium, and Bob's go to regular. ../bazel-bin/cpp/client price --stats_server="xds:///stats.grpcwallet.io" --watch=true --user=Bob ../bazel-bin/cpp/client price --stats_server="xds:///stats.grpcwallet.io" --watch=true --user=Alice
設定其他進階選項
您可以按照下列各節中的指示,設定其他進階流量轉送選項。
斷路機制
斷路機制可讓您設定失敗門檻,避免用戶端要求導致後端服務超載。未完成的要求數量達到您設定的限制後,用戶端就會停止傳送其他要求,讓後端服務有時間復原。
斷路機制會將錯誤傳回給用戶端,而非將後端服務過載,藉此避免連鎖失敗。這樣一來,系統就能同時處理部分流量,並有時間管理超載情況,例如透過自動調整資源調度來處理流量激增情形。
為 stats-service
建立後端服務時,create_service.sh
指令碼會在其設定中加入下列行:
circuitBreakers: maxRequests: 1
這項設定會限制用戶端一次只能向 stats-service
提出一個待處理要求。由於只有一個 wallet-v2
服務,因此執行兩個並行的錢包用戶端 WatchBalance
作業會顯示第二個例項的失敗。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob 2>/dev/null 1>/dev/null & sleep 10 # Wait a few seconds to allow the watch to begin. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
輸出內容如下:
io.grpc.examples.wallet.Client run INFO: Will try to run balance io.grpc.examples.wallet.Client run WARNING: RPC failed: Status{code=INTERNAL, description=RPC to stats server failed: UNAVAILABLE: Cluster max concurrent requests limit exceeded, cause=null}
發出
kill
指令:kill %%
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob 2> /dev/null 1> /dev/null & sleep 10 # Wait a few seconds to allow the watch to begin. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob
輸出內容如下:
server host: error: no hostname failed to fetch balance: rpc error: code = Internal desc = RPC to stats server failed: UNAVAILABLE: Cluster max concurrent requests limit exceeded
發出
kill
指令:kill %%
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob 2>/dev/null 1>/dev/null & sleep 10 # Wait a few seconds to allow the watch to begin. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
輸出內容如下:
Client arguments: command: balance, wallet_server: xds:///wallet.grpcwallet.io, stats_server: localhost:18882, user: Bob, watch: 1 ,unary_watch: 0, observability_project: , route: 13: RPC to stats server failed: UNAVAILABLE: Cluster max concurrent requests limit exceeded
發出
kill
指令:kill %%
錯誤植入
錯誤植入:處理模擬故障的要求時,會產生高延遲、服務超載、服務故障和網路分區等錯誤。這項功能可用於測試服務對模擬故障的彈性。
先前建立網址對應時,您已將錯誤注入政策設為使用 route=fault
標頭,將傳送至 wallet.grpcwallet.io
的 RPC 中斷 50%。
如要示範錯誤注入,請使用下列語言的程式碼。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=fault
輸出內容如下:
server host: grpcwallet-wallet-v2-mig-us-central1-zznc total balance: 10340491 - address: 148de9c5, balance: 2549839 - address: 2e7d2c03, balance: 7790652 io.grpc.examples.wallet.Client run WARNING: RPC failed: Status{code=UNAVAILABLE, description=RPC terminated due to fault injection: HTTP status code 503, cause=null}
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch --user=Bob --route=fault
輸出內容如下:
server host: grpcwallet-wallet-v1-mig-us-central1-bm1t_wallet-v1 user: Bob, total grpc-coin balance: 10452589. - address: 2e7d2c03, balance: 7875108. - address: 148de9c5, balance: 2577481. failed to fetch balance: rpc error: code = Unavailable desc = RPC terminated due to fault injection
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=fault
輸出內容如下:
Client arguments: command: balance, wallet_server: xds:///wallet.grpcwallet.io, stats_server: localhost:18882, user: Bob, watch: 0 ,unary_watch: 1, observability_project: , route: fault server host: grpcwallet-wallet-v2-mig-us-central1-1lm6 user: Bob total grpc-coin balance: 10211908 - address: 148de9c5, balance: 2518132 - address: 2e7d2c03, balance: 7693776 14: Fault injected
串流時間長度上限
可讓所有 RPC 套用逾時上限。這樣一來,如果用戶端忘記設定期限,或設定過長的期限,就不會浪費伺服器資源。
先前建立網址對應時,您已為透過 route=timeout
標頭傳送至 wallet.grpcwallet.io
的 RPC 設定 5 秒的最大串流時間長度。
為了示範逾時情形,我們會先停止 wallet-v2
服務。
gcloud
gcloud compute instance-groups managed resize \ --size=0 grpcwallet-wallet-v2-mig-us-central1 \ --zone=us-central1-a
由於沒有後端服務可處理,且應用程式未設定期限,因此下列指令會永遠卡住。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
指令停止回應。按下 ^C 鍵可中斷指令。
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob
指令停止回應。按下 ^C 鍵可中斷指令。
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
指令停止回應。按下 ^C 鍵可中斷指令。
不過,使用 timeout
路徑的以下指令會在 5 秒後失敗,因為 maxStreamDuration
設定。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob --route=timeout
輸出內容如下:
io.grpc.examples.wallet.Client run WARNING: RPC failed: Status{code=DEADLINE_EXCEEDED, description=deadline exceeded after 4.999594070s. [wait_for_ready, buffered_nanos=5000553401, waiting_for_connection], cause=null}
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob --route=timeout
輸出內容如下:
failed to create stream: rpc error: code = DeadlineExceeded desc = context deadline exceeded.
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob --route=timeout
輸出內容如下:
Client arguments: command: balance, wallet_server: xds:///wallet.grpcwallet.io, stats_server: localhost:18882, user: Bob, watch: 1 ,unary_watch: 0, observability_project: , route: timeout 4: Deadline Exceeded
重新啟動 wallet-v2
服務。
gcloud
gcloud compute instance-groups managed resize \ --size=1 grpcwallet-wallet-v2-mig-us-central1 \ --zone=us-central1-a
重試
重試可讓 gRPC 應用程式根據重試政策重試傳出要求,進而提升服務可用性。在重試政策中,您可以設定失敗要求的重試條件和重試次數上限,例如要求失敗時,是否會傳回特定回應代碼。
先前建立網址對應時,您已為 RPC 設定重試政策,並將 FetchBalance
方法與 membership=premium
標頭搭配使用。這項政策會重試狀態碼為 unavailable
的 RPC,最多重試 3 次。您也為 RPC 設定錯誤注入政策,以 route=account-fault
標頭將 account.grpcwallet.io
的 30% RPC 傳送至 Wallet
服務,並將 Account
服務傳送至 Account
服務。因此,使用 membership=normal
標頭的測試用戶端 30% 的 RPC 會失敗,而使用 membership=premium
標頭的 RPC 失敗率則低於 1%。
如要示範重試,請使用下列語言的程式碼。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java # 30% of the requests fail because Bob is a normal user. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=account-fault # Less than 1% of the requests fail because Alice is a premium user. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --route=account-fault
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client # 30% of the requests fail because Bob is a normal user. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=account-fault # Less than 1% of the requests fail because Alice is a premium user. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --route=account-fault
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp # 30% of the requests fail because Bob is a normal user. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=account-fault # Less than 1% of the requests fail because Alice is a premium user. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --route=account-fault
工作階段相依性
只要執行個體的健康狀態良好並具有容量,工作階段相依性就會盡力將具有特定特性 (HTTP 標頭) 的要求傳送至同一個執行個體。這項功能適用於有狀態的應用程式伺服器,因為當來自特定用戶端的要求傳送至同一個例項,而非輪流分配至不同的例項時,這類伺服器可享有更佳的效能和效率。
建立後端服務 grpcwallet-wallet-v1-affinity-service
時,create_service.sh
指令碼中的 localityLbPolicy
會設為 ROUND_ROBIN
。在這個範例中,您將套用下列設定,將 localityLbPolicy
變更為 RING_HASH
。
sessionAffinity: HEADER_FIELD localityLbPolicy: RING_HASH consistentHash: httpHeaderName: "session_id"
gcloud
儲存後端服務
grpcwallet-wallet-v1-affinity-service
的設定:gcloud compute backend-services export grpcwallet-wallet-v1-affinity-service \ --destination=bs_config.yaml \ --global
更新後端服務
grpcwallet-wallet-v1-affinity-service
:project_id="$(gcloud config list --format 'value(core.project)')" backend_config=" backends: - balancingMode: UTILIZATION capacityScaler: 1.0 group: projects/${project_id}/zones/us-central1-a/instanceGroups/grpcwallet-wallet-v1-mig-us-central1 connectionDraining: drainingTimeoutSec: 0 healthChecks: - projects/${project_id}/global/healthChecks/grpcwallet-health-check loadBalancingScheme: INTERNAL_SELF_MANAGED name: grpcwallet-wallet-v1-affinity-service portName: grpcwallet-wallet-port protocol: GRPC sessionAffinity: HEADER_FIELD localityLbPolicy: RING_HASH consistentHash: httpHeaderName: session_id" gcloud compute backend-services import grpcwallet-wallet-v1-affinity-service --global <<< "${backend_config}"
如要示範工作階段相依性,請使用下列語言的程式碼。使用標記 --affinity=true
時,用戶端會插入標頭 session-id
,其中包含每位使用者的唯一值。這個值的雜湊用於將要求傳送至後端服務 grpcwallet-wallet-v1-affinity-service
執行個體群組中的特定執行個體。
Java
執行下列指令:
cd ~/traffic-director-grpc-examples/java # Without affinity, requests are sent to both instances. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice # With affinity, requests are sent to only one instance. ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --affinity=true
Go
執行下列指令:
cd ~/traffic-director-grpc-examples/go/wallet_client # Without affinity, requests are sent to both instances. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice # With affinity, requests are sent to only one instance. ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --affinity=true
C++
執行下列指令:
cd ~/traffic-director-grpc-examples/cpp # Without affinity, requests are sent to both instances. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice # With affinity, requests are sent to only one instance. ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Alice --affinity=true
還原後端服務 grpcwallet-wallet-v1-affinity-service
的設定。
gcloud
gcloud compute backend-services import grpcwallet-wallet-v1-affinity-service \ --source=bs_config.yaml \ --global
離群值偵測
如要提升服務可用性,請設定異常值偵測功能。這項功能可讓您找出健康狀態不良的主機,並暫時將其從負載平衡集區中移除。這些不健康的主機稱為「異常值」。
gRPC 會根據成功率評估主機,成功率是指主機成功處理要求的頻率。這項費率會受到 gRPC 錯誤、HTTP 錯誤、逾時和其他問題等失敗情形的影響。
透過 Cloud Service Mesh 設定異常值偵測功能時,您可以微調 gRPC 評估主機的方式,以及處理異常值的方式。例如,您可以指定下列條件:
在 gRPC 分析可能的異常狀態之前,主機必須收到的要求數量。
主機偏離平均成功率的程度,超過這個程度就會被視為異常值。
可從負載平衡集區中排除的主機百分比上限。
從負載平衡集區排除異常值的時間長度。
如要進一步瞭解可用的參數,請參閱 REST Resource: backendServices
參考資料。不過,gRPC 有一些限制,請參閱下文。
限制
gRPC 用戶端不支援下列欄位:
outlierDetection.consecutiveErrors
outlierDetection.enforcingConsecutiveErrors
outlierDetection.consecutiveGatewayFailure
outlierDetection.enforcingConsecutiveGatewayFailure
設定離群值偵測
以下程序說明如何為使用單一執行個體群組做為後端的服務,設定異常值偵測功能。這個程序會建立下列設定:
- 系統每秒執行一次異常值偵測分析。您可以使用
interval
欄位設定這項行為。 - 系統會以 30 秒為單位,從負載平衡集區中排除異常值,如下所示:
- 如果主機之前從未被彈出,則只會彈出 30 秒。
- 如果主機先前曾遭到逐出,則每次先前逐出作業都會增加 30 秒的時間。舉例來說,如果主機遭到第三次驅逐,系統會將主機驅逐 90 秒。您可以使用
baseEjectionTime
欄位設定這項行為。
- 如果主機的成功率在所選時間間隔 (在本例中為 1 秒) 內低於平均值 1 標準差,就會視為不健康。您可以使用
successRateStdevFactor
欄位設定最大標準差。
如要以這種方式設定異常值偵測功能,請按照下列步驟操作。
gcloud
使用
gcloud compute backend-services export
指令匯出grpcwallet-wallet-v2-service
後端服務設定檔:gcloud compute backend-services export grpcwallet-wallet-v2-service \ --destination=bs_config.yaml \ --global
在
bs_config.yaml
檔案中,更新grpcwallet-wallet-v2-service
設定,加入異常值偵測欄位:outlierDetection: interval: seconds: 1 nanos: 0 baseEjectionTime: seconds: 30 nanos: 0 successRateStdevFactor: 1000
使用
gcloud compute backend-services import
指令匯入更新的檔案:gcloud compute backend-services import grpcwallet-wallet-v2-service \ --source=bs_config.yaml \ --global
地區負載平衡
如要盡可能有效運用資源,請設定地區負載平衡。這項功能會在後端平均分配用戶端要求,有助於節省資源。
設定區域負載平衡時,您可以使用下表所述的選項。所有選項都需要設定 backendServices
資源。
選項 | 適用的裝置 | 相關設定欄位 |
---|---|---|
使用內建政策 | 所有 gRPC 用戶端 | localityLbPolicy |
使用自訂政策 | 使用 gRPC 1.47 以上版本的 Java 用戶端,且在僅包含 gRPC 用戶端的網格中 | localityLbPolicies
|
定義偏好政策清單 | 使用 gRPC 1.47 以上版本的 Java 用戶端,且在僅包含 gRPC 用戶端的網格中 | localityLbPolicies |
您可以任意搭配使用上述選項。不過,如果您同時設定 localityLbPolicy
和 localityLbPolicies
,gRPC 會先嘗試使用 localityLbPolicies
設定。
如果您未設定區域負載平衡,Cloud Service Mesh 會使用 ROUND_ROBIN
政策。
如要瞭解 ROUND_ROBIN
和其他內建政策,請參閱 backendServices
頁面中 localityLbPolicy
的說明。
使用內建政策
如果您希望所有用戶端都使用單一內建政策,可以透過設定 localityLbPolicy
欄位來選取。
設定這個欄位時,您可以選擇下列政策:
LEAST_REQUEST
(僅限 Java 用戶端)RING_HASH
ROUND_ROBIN
如果不是所有客戶都能使用相同的政策,請參閱定義偏好政策清單。
gcloud
使用
gcloud compute backend-services export
指令匯出grpcwallet-wallet-v2-service
後端服務設定檔:gcloud compute backend-services export grpcwallet-wallet-v2-service \ --destination=bs_config.yaml \ --global
更新匯出的
bs_config.yaml
檔案,加入下列行:localityLbPolicy: -- policy name: RING_HASH
使用 gcloud compute backend-services import 指令匯入更新後的檔案:
gcloud compute backend-services import grpcwallet-wallet-v2-service --source=bs_config.yaml --global
使用自訂政策
如有需要,您可以使用透過 gRPC 建立及部署的自訂負載平衡政策。這項功能適用於使用 gRPC 1.47 以上版本的 Java 用戶端。請只在包含所有 gRPC 用戶端的網格中使用。
建立自訂政策時,您可能會覺得下列文件很實用:
如要讓自訂政策更精細,您可以使用 Open Request Cost Aggregation (ORCA) API。這些 API 可讓您擷取查詢費用和伺服器使用率的各種指標。使用這些 API 需要 gRPC 1.48.1 以上版本。詳情請參閱 gRPC ORCA 範例。
如要瞭解 xDS 如何將自訂負載平衡設定傳送至 gRPC,請參閱「gRPC xDS 自訂負載平衡器設定」。
如要設定 Cloud Service Mesh 使用自訂政策,請使用 localityLbPolicies
欄位來識別政策。
以下步驟說明這個程序。在這個程序中,您會更新 grpcwallet-wallet-v2-service
後端服務的設定,讓連線至該服務的用戶端使用名為 example.ExampleLoadBalancer
的自訂政策。
gcloud
使用
gcloud compute backend-services export
指令匯出grpcwallet-wallet-v2-service
後端服務設定檔:gcloud compute backend-services export grpcwallet-wallet-v2-service \ --destination=bs_config.yaml \ --global
更新匯出的
bs_config.yaml
檔案,以便參照example.ExampleLoadBalancer
政策。加入下列程式碼行:localityLbPolicies: - customPolicy: name: example.ExampleLoadBalancer data: '{ "message": "Hello load-balancing world!" }'
使用 gcloud compute backend-services import 指令匯入更新後的檔案:
gcloud compute backend-services import grpcwallet-wallet-v2-service --source=bs_config.yaml --global
選用:測試負載平衡設定:
Java
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
如果您正確設定自訂負載平衡政策,就會看到您在設定中加入的訊息 (例如「Hello load-balancing world!」)。
定義偏好政策清單
如果您有多個用戶端,但並非所有用戶端都支援單一負載平衡政策,請建立可供用戶端使用的政策清單。使用這個選項時,如果特定用戶端無法使用第一個偏好政策,gRPC 會改用清單中的下一個政策。
建立偏好政策清單時,有效的選項包括自訂政策、ROUND_ROBIN
,以及 Java 用戶端的 LEAST_REQUEST
。最多可列出 10 項政策。
這項功能僅適用於使用 gRPC 1.47 以上版本的 Java 用戶端。請只在包含所有 gRPC 用戶端的網格中使用。
gcloud
- 使用
gcloud compute backend-services export
指令匯出grpcwallet-wallet-v2-service
後端服務設定檔:
gcloud compute backend-services export grpcwallet-wallet-v2-service \ --destination=bs_config.yaml \ --global
更新匯出的
bs_config.yaml
檔案,加入localityLbPolicies
欄位。填入代表下列政策的項目:- 無效的自訂政策 (
example.InvalidLoadBalancer
) - 有效的自訂政策 (
example.ExampleLoadBalancer
) - 支援的內建政策 (
LEAST_REQUEST
)
localityLbPolicies: - customPolicy: name: example.InvalidLoadBalancer data: '{ "message": "This load-balancing policy doesn't work!" }' - customPolicy: name: example.ExampleLoadBalancer data: '{ "message": "Hello load-balancing world!" }' - policy: name: LEAST_REQUEST
- 無效的自訂政策 (
使用 gcloud compute backend-services import 指令匯入更新後的檔案:
gcloud compute backend-services import grpcwallet-wallet-v2-service --source=bs_config.yaml --global
選用:測試負載平衡設定:
Java
cd ~/traffic-director-grpc-examples/java ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
在回應中,gRPC 嘗試尋找
example.InvalidLoadBalancer
,但失敗。之後,系統會改為使用example.ExampleLoadBalancer
,您會看到在設定中加入的訊息 (「Hello load-balancing world!」)。用戶端上的 gRPC 記錄包含一則訊息,指出找不到example.InvalidLoadBalancer
。
清除資源
如要清除資源,請在本機系統中執行下列指令:
traffic-director-grpc-examples/scripts/cleanup.sh
封鎖服務間的流量
如果您想封鎖服務 A 和服務 B 之間的流量,且部署作業是在 GKE 上執行,請設定服務安全性,並使用授權政策封鎖服務間的流量。如需完整操作說明,請參閱「Cloud Service Mesh 服務安全性」和Envoy 與無 Proxy gRPC的設定說明。
後續步驟
- 如要瞭解如何解決 Cloud Service Mesh 設定問題,請參閱解決使用無 Proxy gRPC 的部署問題。