通过高级流量管理设置无代理 gRPC 服务

本文档提供了有关使用以下路由功能配置 Traffic Director 的端到端说明:

  • 路由匹配
  • 流量拆分

如需了解有关这些功能的概念信息,请参阅高级流量管理

为了说明这些功能,您将部署一个 gRPC Wallet 示例。如下图所示,您将为 wallet-servicestats-serviceaccount-service 创建后端服务。

gRPC Wallet 流量路由配置示例(点击可放大)
gRPC Wallet 流量路由配置示例(点击可放大)

在此示例中,您将部署每项服务的多个版本,以根据您所配置的规则说明请求路由。为了模拟服务的不同版本的构建和部署,您将使用服务器标志来更改仅构建一次的二进制文件的行为。

  • --port 标志指定后端虚拟机上的服务侦听的端口。
  • --hostname_suffix 标志指定附加到响应请求的虚拟机主机名的值。结果值将作为 hostname 元数据添加到响应中。这有助于您确定后端服务的哪个实例响应了客户端请求。
  • 值为 true--premium_only 标志指定该服务是 stats 服务的高级版本。
  • 值为 true--v1_behavior 标志指定 Wallet 二进制文件充当 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 2 --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

创建 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

  1. 创建实例模板。

    gcloud compute instance-templates create grpcwallet-account-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --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
    curl -L https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples/archive/master.tar.gz | tar -xz
    cd traffic-director-grpc-examples-master/go/account_server/
    sudo apt-get install -y golang git
    go build .
    sudo systemd-run ./account_server --port 50053 --hostname_suffix account')
    

创建代管实例组

代管实例组会根据需要使用自动扩缩功能创建新的后端虚拟机。在本部分中,您将使用在上一部分中创建的实例模板创建代管实例组。

gcloud

  1. 创建实例组。

    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

  1. 创建已命名端口。

    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,然后将运行状况检查和实例组与后端服务相关联。在此示例中,您将使用在创建代管实例组中创建的代管实例组。此代管实例组运行 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 示例中使用的其余后端服务的步骤与上述步骤类似。您可以通过运行 Shell 脚本来创建其余服务。该脚本会部署以下后端服务:

  • stats
  • stats-premium
  • wallet-v1
  • wallet-v2

运行创建额外后端服务的 Shell 脚本:

curl -O https://raw.githubusercontent.com/GoogleCloudPlatform/traffic-director-grpc-examples/master/scripts/create_service.sh
chmod +x ./create_service.sh

./create_service.sh go stats 50052 stats '--account_server="xds:///account.grpcwallet.io"'

./create_service.sh go stats 50052 stats-premium '--account_server="xds:///account.grpcwallet.io" --premium_only=true'

./create_service.sh java wallet 50051 wallet-v1 '--account_server="xds:///account.grpcwallet.io" --stats_server="xds:///stats.grpcwallet.io" --v1_behavior=true'

./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 中配置一个值为 account.grpcwallet.iohosts 条目。

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

运行以下命令以创建网址映射:

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:
    - fullPathMatch: /grpc.examples.wallet.Wallet/FetchBalance
    priority: 0
    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: 1
    routeAction:
      weightedBackendServices:
      - backendService: projects/$PROJECT_ID/global/backendServices/grpcwallet-wallet-v2-service
        weight: 100
EOF

创建目标代理和转发规则

在本部分中,您将创建目标 gRPC 代理和转发规则。

目标 gRPC 代理会引用您在上一步中创建的网址映射。--validate-for-proxyless 标志会启用配置检查,这样您就不会在无意中启用与无代理 gRPC 部署不兼容的功能。

gcloud

  1. 创建目标 gRPC 代理。

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

转发规则会引用您创建的目标 gRPC 代理。负载平衡方案设置为 INTERNAL_SELF_MANAGED,以指示此转发规则会由 Traffic Director 使用。此规则必须是全局转发规则。IP 地址设置为 0.0.0.0,因为无代理 gRPC 客户端通过向 Traffic Director 发送 LDS 请求(而不是执行 DNS 查找)来解析目标 URI 中的 hostname:port。如需了解详情,请参阅名称解析方案

如果目标 URI 中未指定端口,则默认值为 80。例如,目标 URI xds:///foo.myservice:8080 与使用端口 8080 配置的转发规则匹配。在此示例中,转发规则是使用端口 80 进行配置的。

gcloud

  1. 创建转发规则。

    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
    

验证配置

配置过程完成后,请通过检查控制台中的 Traffic Director 页面来验证您配置的后端服务是否可用。请确认后端服务和关联的后端报告为运行状况良好。

验证路由配置

在本部分中,您将验证路由配置是否正常工作。您可以使用 grpcurl 工具测试配置。

gcloud

  1. 创建客户端虚拟机,用于运行客户端以测试服务。

    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.9.0.tar.gz | tar -xz
    ./td-grpc-bootstrap-0.9.0/td-grpc-bootstrap | tee $GRPC_XDS_BOOTSTRAP')
    
  2. 使用 SSH 访问虚拟机。

为了在没有 Sidecar 代理的情况下访问服务,gRPC 客户端需要使用 xds 名称解析方案。此方案指示客户端所用的 gRPC 库使用 xDS 服务器来解析主机名。为此,您需要用到引导配置。上一部分中的启动脚本会设置 GRPC_XDS_BOOTSTRAP 环境变量,并使用帮助程序脚本生成引导文件。所生成引导文件中 TRAFFICDIRECTOR_GCP_PROJECT_NUMBERTRAFFICDIRECTOR_NETWORK_NAME 和 zone 的值将从知道 Compute Engine 虚拟机实例这些详细信息的元数据服务器获取。您可以使用 -gcp-project-number-vpc-network-name 选项手动将这些值提供给帮助程序脚本。

使用 grpcurl 工具验证配置

首先,安装 grpcurl 工具。

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

接下来,运行以下命令以验证 AccountStatsWallet 服务是否正在运行。

$ ./grpcurl -plaintext xds:///account.grpcwallet.io list
grpc.examples.wallet.account.Account
grpc.health.v1.Health
grpc.reflection.v1alpha.ServerReflection

$ ./grpcurl -plaintext -d '{"token": "2bd806c9"}' xds:///account.grpcwallet.io grpc.examples.wallet.account.Account/GetUserInfo
{
  "name": "Alice",
  "membership": "PREMIUM"
}

$ ./grpcurl -plaintext -H 'authorization:2bd806c9' -H 'membership:premium' xds:///stats.grpcwallet.io grpc.examples.wallet.stats.Stats/FetchPrice
{
  "price": "10295"
}

$ ./grpcurl -plaintext -H 'authorization:2bd806c9' -H 'membership:premium' -d '{"include_balance_per_address": true}' xds:///wallet.grpcwallet.io grpc.examples.wallet.Wallet/FetchBalance
{
  "balance": "5089953"
}

使用 grpc-wallet 客户端进行验证

使用以下特定于语言的说明来验证配置。以下命令会发送多个 RPC(一些 RPC 具有额外的元数据),以显示系统根据网址映射中的匹配规则将请求路由到后端服务。以下命令还会输出每个响应的后端主机名,以显示请求所路由到的后端服务。

C++

  1. 如需使用 gRPC C++ 客户端验证服务,请运行以下命令:

    sudo apt-get update
    sudo apt-get install -y build-essential git
    
    git clone https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git
    cd traffic-director-grpc-examples/cpp
    ../tools/bazel build :client
    
    # This command calls FetchBalance from the 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 the 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 the 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 goes 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
    

Go

  1. 如需使用 gRPC Go 客户端验证服务,请运行以下命令:

    sudo apt-get update
    sudo apt install -y golang git
    
    git clone https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git
    cd traffic-director-grpc-examples/go/wallet_client
    go build .
    
    # This command calls FetchBalance from the 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 the 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 the 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 goes 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
    

Java

  1. 如需使用 gRPC Java 客户端验证服务,请运行以下命令:

    sudo apt-get update
    sudo apt-get install -y openjdk-11-jdk-headless git
    
    git clone https://github.com/GoogleCloudPlatform/traffic-director-grpc-examples.git
    cd traffic-director-grpc-examples/java
    ./gradlew installDist
    
    # This command calls FetchBalance from the 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 the 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 the 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 goes 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
    

清理资源

运行以下脚本以清理资源。

bash <(curl -s https://raw.githubusercontent.com/GoogleCloudPlatform/traffic-director-grpc-examples/master/scripts/cleanup.sh)
gcloud compute instances delete grpc-wallet-client --zone us-central1-a -q

后续步骤

如果您在配置过程中遇到意外行为,请参阅排查无代理 Traffic Director 部署问题以及无代理 gRPC 应用的 Traffic Director 限制