プロキシレス gRPC サービスを使用した高度なトラフィック管理を構成する

このドキュメントでは、次のルーティング機能を使用して Traffic Director を構成する手順について説明します。

  • ルート マッチング
  • トラフィック分割
  • 回路遮断
  • フォールト インジェクション
  • 最大ストリーミング期間

このドキュメントでは、Compute Engine でのプロキシレス gRPC を使用した高度なトラフィック管理の設定を中心に説明しますが、Google Kubernetes Engine(GKE)でプロキシレス gRPC を使用する場合は、高度なトラフィック管理もサポートされています。

始める前に

高度なトラフィック管理を構成する前に、プロキシレス gRPC サービスを使用した Traffic Director の設定の準備の要件をご確認ください。すべての要件が満たされていなければ、高度なトラフィック管理を構成することはできません。

これらの機能のコンセプトに関する情報については、高度なトラフィック管理をご覧ください。

gRPC Wallet の例について

gRPC Wallet のサンプルのデプロイを例に、この機能を説明します。次の図のように、wallet-servicestats-serviceaccount-service のバックエンド サービスを作成します。

gRPC Wallet のトラフィック ルーティング構成の例。
gRPC Wallet のトラフィック ルーティング構成の例(クリックして拡大)

この例では、構成したルールに基づいたリクエストのルーティングを説明するため、サービスごとに複数のバージョンをデプロイします。異なるバージョンのサービスのビルドとデプロイをシミュレートするには、サーバーフラグを使用して、1 回のみビルドするバイナリの動作を変更します。

  • --port フラグには、バックエンド VM 上のサービスがリッスンするポートを指定します。
  • --hostname_suffix フラグには、リクエストに応答する VM のホスト名に追加される値を指定します。生成される値は、レスポンスの hostname メタデータとして追加されます。これは、クライアント リクエストに応答したバックエンド サービスのインスタンスの識別に役立ちます。
  • --premium_only フラグに値 true を指定すると、サービスが stats サービスのプレミアム バージョンになります。
  • --v1_behavior フラグに値 true を指定すると、ウォレットのバイナリが v1 バージョンとして動作します。

次の表に、ウォレットの例のバックエンド サービス(サービス)、インスタンス グループ、インスタンスごとに、これらのフラグの値を示します。

バックエンド サービス インスタンス グループ インスタンス サーバーフラグ
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 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"

次に、以下の表のルーティング ルールに基づいて、テスト クライアントから上に示したサービスにリクエストをルーティングするように Traffic Director を構成します。

ホスト 一致ルール ルート アクション
wallet.grpcwallet.io デフォルト wallet-v1
フルパス: /grpc.examples.wallet.Wallet/FetchBalance wallet-v1: 40%
wallet-v2: 60%
パス接頭辞: /grpc.examples.wallet.Wallet/ wallet-v2
stats.grpcwallet.io デフォルト stats
パス接頭辞: "/"
ヘッダー: {"membership": "premium"}
stats-premium
account.grpcwallet.io デフォルト account

ローカルの環境を準備する

これらの例で必要な環境を設定するには、次のコマンドを実行します。

  1. gcloud バイナリを更新して、最新バージョンであることを確認します。

    gcloud components update
    
  2. サンプル リポジトリをダウンロードします。

    sudo apt-get install git -y
    
  3. EXAMPLES_VERSION の値を設定し、サンプルに適切なリポジトリのクローンを作成します。

    export EXAMPLES_VERSION=v1.0.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

  1. Cloud Router インスタンスを作成します。

    gcloud compute routers create nat-router-us-central1 \
        --network=default \
        --region=us-central1
    
  2. 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

  1. ヘルスチェックを作成します。

    gcloud compute health-checks create grpc grpcwallet-health-check \
        --use-serving-port
    
  2. ヘルスチェック用のファイアウォール ルールを作成します。

    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
    sudo apt-get install -y golang git
    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

  1. バックエンド サービスを作成し、新しいバックエンド サービスにヘルスチェックを関連付けます。

    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
    
  2. マネージド インスタンス グループをバックエンドとして追加します。

    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-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'

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"'

ルーティング ルールを作成する

このセクションでは、この例のサービスの仮想ホスト名と、関連するルーティング ルールを指定する URL マップを作成します。詳細については、ルーティング ルールマップをご覧ください。

URL マップでは、この例のサービスのホスト名を hostRules で指定します。これらのホスト名は、特定のサービスに接続するためにクライアントがチャンネル URI で使用する名前です。たとえば、account サービスにリクエストを送信する場合は、クライアントがチャンネル URI で xds:///account.grpcwallet.io を使用します。hostRules で、account.grpcwallet.io という値を持つ hosts エントリを構成します。

hosts エントリに関連付けられた pathMatcher は、その仮想ホストのすべてのルーティング ルールを含む pathMatcher の名前を指定します。pathMatcher 構成は、マッチング ルールと対応するアクション ルールで構成されます。この例では、次の構成になります。

  • リクエストが account.grpcwallet.io に送信された場合、そのリクエストは grpcwallet-account-service バックエンド サービスに送信されます。
  • リクエストが stats.grpcwallet.io に送信された場合、次のようになります。
    • リクエストに値が premium のヘッダー membership が含まれている場合、そのリクエストは grpcwallet-stats-premium-service バックエンド サービスに送信されます。
    • それ以外の場合は、リクエストはデフォルトのバックエンド サービス grpcwallet-stats-service に送信されます。
  • リクエストが wallet.grpcwallet.io に送信された場合、次のようになります。

    • ServiceName または MethodName/grpc.examples.wallet.Wallet/FetchBalance と一致する場合、このようなリクエストの 40% が grpcwallet-wallet-v2-service バックエンド サービスに、残りのリクエストが grpcwallet-wallet-v1-service バックエンド サービスに送信されます。
    • それ以外の場合は、ServiceName/grpc.examples.wallet.Wallet/ と一致すれば、呼び出されたメソッドに関係なく、リクエストは grpcwallet-wallet-v1-service バックエンド サービスに送信されます。

gcloud

URL マップを作成します。

export PROJECT_ID=$(gcloud config list --format 'value(core.project)')

gcloud compute url-maps import grpcwallet-url-map << EOF
defaultService: projects/$PROJECT_ID/global/backendServices/grpcwallet-account-service
name: grpcwallet-url-map

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:
- defaultService: projects/$PROJECT_ID/global/backendServices/grpcwallet-account-service
  name: grpcwallet-account-path-matcher

- defaultService: projects/$PROJECT_ID/global/backendServices/grpcwallet-stats-service
  name: grpcwallet-stats-path-matcher
  routeRules:
  - matchRules:
    - prefixMatch: /
      headerMatches:
      - headerName: membership
        exactMatch: premium
    priority: 0
    service: projects/$PROJECT_ID/global/backendServices/grpcwallet-stats-premium-service

- defaultService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v1-service
  name: grpcwallet-wallet-path-matcher
  routeRules:
  - matchRules:
    - prefixMatch: /
      headerMatches:
      - headerName: route
        exactMatch: timeout
    priority: 0
    routeAction:
      weightedBackendServices:
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v2-service
        weight: 100
      maxStreamDuration:
        seconds: 5

  - matchRules:
    - prefixMatch: /
      headerMatches:
      - headerName: route
        exactMatch: fault
    priority: 1
    routeAction:
      weightedBackendServices:
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v2-service
        weight: 100
      faultInjectionPolicy:
        abort:
          httpStatus: 503
          percentage: 50

  - matchRules:
    - fullPathMatch: /grpc.examples.wallet.Wallet/FetchBalance
    priority: 2
    routeAction:
      weightedBackendServices:
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v2-service
        weight: 40
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v1-service
        weight: 60

  - matchRules:
    - prefixMatch: /grpc.examples.wallet.Wallet/
    priority: 3
    routeAction:
      weightedBackendServices:
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v2-service
        weight: 100
EOF

ターゲット プロキシと転送ルールを作成する

このセクションでは、ターゲット gRPC プロキシと転送ルールを作成します。

ターゲット gRPC プロキシは、前のステップで作成した URL マップを参照します。--validate-for-proxyless フラグを指定すると、構成チェックが有効になり、プロキシレス gRPC デプロイと互換性のない機能が誤って有効にならないようにできます。

gcloud

  • ターゲット gRPC プロキシを作成します。

    gcloud compute target-grpc-proxies create grpcwallet-proxy \
       --url-map=grpcwallet-url-map \
       --validate-for-proxyless
    

作成したターゲット gRPC プロキシが転送ルールによって参照されます。負荷分散スキームが INTERNAL_SELF_MANAGED に設定され、この転送ルールが Traffic Director によって使用されていることを示します。これはグローバル転送ルールである必要があります。プロキシレス gRPC クライアントは、DNS ルックアップを実行する代わりに LDS リクエストを Traffic Director に送信することで、ターゲット URI で hostname:port を解決するため、IP アドレスは 0.0.0.0 に設定されます。詳細については、名前解決スキームをご覧ください。

ターゲット 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 Console の [Traffic Director] ページで、構成したバックエンド サービスが使用可能であることを確認します。バックエンド サービスと関連するバックエンドが正常であると報告されていることを確認します。

ルーティング構成を確認する

このセクションでは、ルーティング構成が正しく機能していることを確認します。grpcurl ツールを使用して構成をテストします。

gcloud

  1. クライアントを実行するクライアント 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.11.0.tar.gz | tar -xz
    ./td-grpc-bootstrap-0.11.0/td-grpc-bootstrap | sudo tee $GRPC_XDS_BOOTSTRAP')
    
  2. SSH を使用して VM にアクセスし、次のコマンドを実行して VM を準備します。

    export EXAMPLES_VERSION=v1.0.x
    sudo apt-get update
    sudo apt-get install git -y
    
  3. 次のコマンドを実行します。

    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
    

サイドカー プロキシなしでサービスにアクセスするには、gRPC クライアントが xds 名前解決スキームを使用する必要があります。このスキームは、クライアントで使用される gRPC ライブラリに、xDS サーバーを使用してホスト名を解決するように指示します。これを実行するには、ブートストラップの構成が必要です。

前のセクションの起動スクリプトで GRPC_XDS_BOOTSTRAP 環境変数を設定し、ヘルパー スクリプトを使用してブートストラップ ファイルを生成します。生成されたブートストラップ ファイル内の TRAFFICDIRECTOR_GCP_PROJECT_NUMBERTRAFFICDIRECTOR_NETWORK_NAME、ゾーンの値は、Compute Engine VM インスタンスの詳細を把握しているメタデータ サーバーから取得されます。これらの値は、-gcp-project-number オプションと -vpc-network-name オプションを使用してヘルパー スクリプトに手動で指定できます。

grpcurl ツールを使用して構成を確認する

SSH シェルで次のコマンドを実行して、wallet-servicestats-serviceaccount-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(追加のメタデータを含む)が送信され、URL マップのマッチング ルールに基づいてバックエンド サービスにリクエストがルーティングされます。リクエストがルーティングされたバックエンド サービスを示す各レスポンスのバックエンド ホスト名も出力されます。

Java

  1. gRPC Java クライアントでサービスを確認するには、次のコマンドを実行します。

    sudo apt-get install -y openjdk-11-jdk-headless
    
  2. 次のコマンドを実行します。

    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' (40%)
    # and 'wallet-v2' (60%).
    ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true
    
    # 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
    
    # 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

  1. gRPC Go クライアントでサービスを確認するには、次のコマンドを実行します。

    sudo apt install -y golang
    
  2. 次のコマンドを実行します。

    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' (40%)
    # and 'wallet-v2' (60%).
    ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch
    
    # 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
    
    # 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++

  1. gRPC C++ クライアントでサービスを確認するには、次のコマンドを実行します。

    sudo apt-get install -y build-essential
    
  2. 次のコマンドを実行します。

    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' (40%) and 'wallet-v2' (60%).
    ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true
    
    # 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
    
    # 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 に保留できるリクエストは 1 つに制限されます。wallet-v2 サービスは 1 つのみ存在するため、2 つのウォレット クライアントで WatchBalance オペレーションを同時実行すると、2 番目のインスタンスで障害が発生します。

Java

  1. 次のコマンドを実行します。

    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
    
  2. 出力は次のようになります。

    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}
    
  3. kill コマンドを発行します。

    kill %%
    

Go

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/go
    ./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
    
  2. 出力は次のようになります。

    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
    
  3. kill コマンドを発行します。

    kill %%
    

C++

  1. 次のコマンドを実行します。

    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
    
  2. 出力は次のようになります。

    Client arguments: command: balance, wallet_server: xds:///wallet.grpcwallet.io, stats_server:
    localhost:18882, user: Bob, watch: 1 ,unary_watch: 0, observability_project: , route:
    14: Cluster max concurrent requests limit exceeded
    
  3. kill コマンドを発行します。

    kill %%
    

フォールト インジェクション

フォールト インジェクションは、高レイテンシ、サービス過負荷、サービス障害、ネットワーク パーティショニングなどの障害をシミュレートするリクエストを処理する際にエラーを発生させます。この機能は、サービスの復元力を疑似的にテストするために利用できます。

先ほど URL マップを作成した際に、route=fault ヘッダーを使用した wallet-service のフォールト インジェクションを 50% に設定しました。

フォールト インジェクションを実証するには、次の言語でコードを使用します。

Java

  1. 次のコマンドを実行します。

    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
    
  2. 出力は次のようになります。

    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=HTTP status code 503, cause=null}
    

Go

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/go
    ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch --user=Bob --route=fault
    
  2. 出力は次のようになります。

     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++

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/cpp
    ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --unary_watch=true --user=Bob --route=fault
    
  2. 出力は次のようになります。

    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 に最大タイムアウトを適用できます。これにより、クライアントが期限の設定を忘れたり、長すぎる期限を設定したりすることによって、サーバー リソースを無駄にすることがなくなります。

上の URL マップを作成した際に、route=timeout ヘッダーを使用して、wallet-service に対する RPC の最大ストリーミング期間を 5 秒に設定しました。

タイムアウトを確認するには、まず wallet-v2 サービスを停止します。

gcloud

gcloud compute instance-groups managed resize \
    --size=0 grpcwallet-wallet-v2-mig-us-central1 \
    --zone=us-central1-a

処理するバックエンド サービスが存在せず、アプリケーションが期限を設定しないため、通常の watch コマンドは恒久的に停止します。

Java

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/java
    ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
    
  2. コマンドがレスポンスを停止します。コマンドを中断するには、^C キーを押してください。

Go

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/go
    ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob
    
  2. コマンドがレスポンスを停止します。コマンドを中断するには、^C キーを押してください。

C++

  1. 次のコマンドを実行します。

    cd ~/traffic-director-grpc-examples/cpp
    ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob
    
  2. コマンドがレスポンスを停止します。コマンドを中断するには、^C キーを押してください。

ただし、timeout ルートを使用する場合は、maxStreamDuration 設定により、5 秒後に watch が失敗します。

Java

  1. 次のコマンドを実行します。

    ./build/install/wallet/bin/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob --route=timeout
    
  2. 出力は次のようになります。

    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

  1. 次のコマンドを実行します。

    ./wallet_client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch --user=Bob --route=timeout
    
  2. 出力は次のようになります。

    failed to create stream: rpc error: code = DeadlineExceeded desc = context deadline exceeded.
    

C++

  1. 次のコマンドを実行します。

    ../bazel-bin/cpp/client balance --wallet_server="xds:///wallet.grpcwallet.io" --watch=true --user=Bob --route=timeout
    
  2. 出力は次のようになります。

    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
    

リソースをクリーンアップする

リソースをクリーンアップするには、ローカル システムから次のコマンドを実行します。

traffic-director-grpc-examples/scripts/cleanup.sh

次のステップ