使用无代理 gRPC 应用实现可观测性

本文档介绍了如何将 gRPC 的可观测性功能与使用 Traffic Director 的服务搭配使用。借助这些功能,您将能够访问监控和跟踪记录指标,以帮助您解决部署存在的问题。

此外还介绍了如何将信息导出到 Cloud TraceCloud Monitoring

前提条件

若要创建本文档中的示例,请执行以下操作:

某些可观测性功能需要 gRPC 应用的附加命令行参数;本文档介绍了这些参数。本文档中介绍的特性和功能均属于 gRPC 库。您无需进一步配置 Traffic Director。

指标和跟踪记录

gRPC 客户端和服务器与 OpenCensus 集成,以将指标和跟踪记录导出到各种后端,包括 Trace 和 Monitoring。本文档提供了采用以下 gRPC 语言的示例:

  • C++
  • Go
  • Java

采用其他语言的 OpenCensus 实现可能支持本文档中介绍的部分功能,但我们无法保证这些功能将正常运行。 如需了解详情,请参阅 OpenCensus 文档

启用指标和跟踪记录后,gRPC 客户端和服务器会导出视图,这些视图是针对给定指标的聚合,在 OpenCensus gRPC 指标规范中指定:

  • grpc.io/{client,server}/sent_bytes_per_rpc
  • grpc.io/{client,server}/received_bytes_per_rpc
  • grpc.io/{client,server}/sent_messages_per_rpc
  • grpc.io/{client,server}/received_messages_per_rpc
  • grpc.io/{client,server}/started_rpcs
  • grpc.io/client/roundtrip_latency
  • grpc.io/server/server_latency

启用 Cloud Monitoring 和 Cloud Trace API

gRPC 的 OpenCensus 集成支持多种后端以导出指标和跟踪记录。以下示例演示了如何将此信息导出到 Monitoring 和 Trace。在本文档其他位置的依赖项中,这些统称为 stackdriver

若要使这些示例工作并让您在项目的 Google Cloud 控制台上直观呈现指标和跟踪记录,请按照说明启用 Monitoring APICloud Trace API

对 gRPC 应用进行插桩处理

gRPC Wallet 示例代码已针对指标和跟踪进行插桩处理。如需启用指标和跟踪,请使用以下命令行 flag 运行 gRPC 客户端和服务器:

 --gcp_client_project=PROJECT_ID

PROJECT_ID 替换为项目的 ID。如果您使用 gRPC Wallet 示例代码库中的 create_service.sh script(如使用无代理 gRPC 配置高级流量管理中所述),请添加此标志作为提供给 Shell 脚本的最后一个参数。

例如:

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

将插桩添加到现有 gRPC 应用所需的代码更改如下所示。作为您自己的应用中的最佳做法,我们建议通过命令行标志或环境变量对插桩代码进行门控,以允许无代理 gRPC 部署动态选择启用或停用指标和跟踪记录,而无需进行额外的代码更改。

以下示例代码演示了如何同时配置指标和跟踪记录。您还可以单独进行配置,也可使用其中一个但不使用另一个。以下代码展示了如何同时配置它们,因为两者的步骤类似。

C++

OpenCensus gRPC C++ 插件需要使用 Bazel 进行构建。您必须修改两个构建文件以包含 OpenCensus 依赖项。

  1. 请将以下内容添加到 WORKSPACE 文件:

    load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language")
    
    http_archive(
        name = "com_google_googleapis",
        sha256 = "150be57ff83646e5652e03683c949f0830d9a0e73ef787786864210e45537fe0",
        strip_prefix = "googleapis-6e3b55e26bf5a9f7874b6ba1411a0cc50cb87a48",
       urls =       ["https://github.com/googleapis/googleapis/archive/6e3b55e26bf5a9f7874b6ba1411a0cc50cb87a48.zip"],
    )
    
    switched_rules_by_language(
        name = "com_google_googleapis_imports",
        cc = True,
        grpc = True,
    )
    
  2. 将以下依赖项添加到 BUILD 文件中的构建目标:

    cc_binary(
       name = "client",
       srcs = ["client.cc"],
       defines = ["BAZEL_BUILD"],
       deps = [
           # New dependencies:
           "@com_github_grpc_grpc//:grpc_opencensus_plugin",
           "@io_opencensus_cpp//opencensus/trace:trace",
           "@io_opencensus_cpp//opencensus/stats:stats",
           "@io_opencensus_cpp//opencensus/exporters/trace/stackdriver:stackdriver_exporter",
           "@io_opencensus_cpp//opencensus/exporters/stats/stackdriver:stackdriver_exporter",
       ],
    )
    
  3. 对 C++ 应用进行插桩处理。客户端和服务器均在进程内进行全局插桩处理,如下所示:

    #include <grpcpp/opencensus.h>
    #include "opencensus/exporters/stats/stackdriver/stackdriver_exporter.h"
    #include "opencensus/exporters/trace/stackdriver/stackdriver_exporter.h"
    
    ABSL_FLAG(std::string, gcp_client_project, "", "Google Cloud project for metric/trace uploads");
    
    int main(int argc, char** argv) {
      // Optionally configure OpenCensus before using gRPC
      if (!absl::GetFlag(FLAGS_gcp_client_project).empty()) {
        grpc::RegisterOpenCensusPlugin();
        grpc::RegisterOpenCensusViewsForExport();
        // For demo purposes, always sample (probability=1.0)
        opencensus::trace::TraceConfig::SetCurrentTraceParams(
            {128, 128, 128, 128, opencensus::trace::ProbabilitySampler(1.0)});
        opencensus::exporters::trace::StackdriverOptions trace_opts;
        trace_opts.project_id = absl::GetFlag(FLAGS_gcp_client_project);
        opencensus::exporters::trace::StackdriverExporter::Register(std::move(trace_opts));
        opencensus::exporters::stats::StackdriverOptions stats_opts;
        stats_opts.project_id = absl::GetFlag(FLAGS_gcp_client_project);
        // This must be unique among all processes exporting to Stackdriver
        stats_opts.opencensus_task = "wallet-server-" + std::to_string(getpid());
        opencensus::exporters::stats::StackdriverExporter::Register(std::move(stats_opts));
      }
    
      // Now use gRPC as usual.
    }
    

Go

对于 Go,请按以下步骤操作。

  1. 使用 ClientHandler 对客户端进行插桩:

    import (
      "go.opencensus.io/plugin/ocgrpc"
      "go.opencensus.io/stats/view"
      "go.opencensus.io/trace"
      "contrib.go.opencensus.io/exporter/stackdriver"
    )
    
    if gcpClientProject != "" {
        view.Register(ocgrpc.DefaultClientViews...)
        sd, err := stackdriver.NewExporter(stackdriver.Options{
            ProjectID:    gcpClientProject,
        })
        defer sd.Flush()
        trace.RegisterExporter(sd)
        sd.StartMetricsExporter()
        defer sd.StopMetricsExporter()
        trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
    
        channel, err := grpc.Dial(serverAddr, grpc.WithInsecure(),
           grpc.WithStatsHandler(new(ocgrpc.ClientHandler)))
    }
    
  2. 使用 ServerHandler 对服务器进行插桩:

    import (
      "go.opencensus.io/plugin/ocgrpc"
      "go.opencensus.io/stats/view"
      "go.opencensus.io/trace"
      "contrib.go.opencensus.io/exporter/stackdriver"
    )
    
    if gcpClientProject != "" {
        view.Register(ocgrpc.DefaultServerViews...)
        sd, err := stackdriver.NewExporter(stackdriver.Options{
            ProjectID:    gcpClientProject,
        })
        defer sd.Flush()
        trace.RegisterExporter(sd)
        sd.StartMetricsExporter()
        defer sd.StopMetricsExporter()
        trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
    
        srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
    }
    

Java

对于 Java,将以下依赖项添加到 build.gradle 文件中:

def opencensusVersion = "0.28.0"
def grpcVersion = "1.35.0"

dependencies {
  // New dependencies:
  compile "io.grpc:grpc-census:{$grpcVersion}",
               "io.opencensus:opencensus-api:${opencensusVersion}",
               "io.opencensus:opencensus-contrib-grpc-metrics:${opencensusVersion}",
               "io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}",
               "io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}"
 runtime "io.opencensus:opencensus-impl:${opencensusVersion}"
}

对于 Java 客户端和服务器,添加 io.grpc:grpc-census 的依赖项会自动将指标和跟踪记录插桩添加到 RPC 中。但是,您需要指定一个 OpenCensus 导出器以获取数据:

import io.opencensus.contrib.grpc.metrics.RpcViews;
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
import io.opencensus.trace.Tracing;
import io.opencensus.trace.config.TraceConfig;
import io.opencensus.trace.samplers.Samplers;

if (gcpClientProject != "") {
  // Configure export to Monitoring and Trace
  RpcViews.registerAllViews();
  TraceConfig traceConfig = Tracing.getTraceConfig();
  traceConfig.updateActiveTraceParams(
      traceConfig.getActiveTraceParams().toBuilder()
          .setSampler(Samplers.alwaysSample())
          .build());

  StackdriverStatsExporter.createAndRegister(
      StackdriverStatsConfiguration.builder().setProjectId(gcpClientProject).build());
  StackdriverTraceExporter.createAndRegister(
      StackdriverTraceConfiguration.builder().setProjectId(gcpClientProject).build());
}

在 Monitoring 信息中心中查看指标

对应用进行插桩后,gRPC 指标会导出到 Monitoring,并可在 Google Cloud 控制台的 Metrics Explorer 中查看。

控制台

要查看指标,请执行以下操作:

  1. 在 Google Cloud Console 中,转到 Monitoring 页面。

    进入 Monitoring

  2. 在左侧的导航栏中,点击 Metrics Explorer

  3. 构建您的查询 (Build Your Query) 下,选择虚拟机实例GKE 容器作为资源类型。

  4. 指标字段中,选择指标和跟踪记录中列出的任何指标名称,例如 OpenCensus/grpc.io/client/roundtrip_latency

  5. 聚合器 (Aggregator) 下拉列表中,选择平均值作为类型。您会看到类似于下面这样的图表:

    Metrics Explorer。
    Metrics Explorer(点击可放大)

    除了标准 Monitoring 详细视图(例如,过滤以仅查看特定实例组的统计信息)之外,您还可以按 grpc_client_methodgrpc_server_method 细分统计信息,因为由 OpenCensus 发送的每个指标均使用相应的 gRPC 方法名称进行注解。

    您可以将这些指标视图整合到 Monitoring 信息中心和图表中,并将其用作自动提醒的基础。

通过 Trace 查看跟踪记录

完成设置过程后,经过插桩的 gRPC 客户端和服务器会将跟踪记录发送到 Trace。Google Cloud 控制台中的跟踪记录概览页面会显示最近的跟踪记录列表。您可以选择一条跟踪记录来查看流量明细,它会显示类似于以下部分中描述的内容。

Trace 与 Envoy 代理的兼容性

使用 Envoy 实现可观测性中所述,通过 Traffic Director 和 Envoy 代理将跟踪记录导出到 Trace 会使用 Envoy 的 OpenCensus 跟踪器配置,这使得从无代理 gRPC 应用和 Envoy 代理导出的跟踪记录能够在服务网格中完全兼容。为了与无代理 gRPC 兼容,Envoy 引导需要配置跟踪记录上下文,以在其 OpenCensusConfig 中添加 GRPC_TRACE_BIN 跟踪记录格式。例如:

tracing:
  http:
      name: envoy.tracers.opencensus
      typed_config:
        "@type": type.googleapis.com/envoy.config.trace.v2.OpenCensusConfig
        stackdriver_exporter_enabled: "true"
        stackdriver_project_id: "PROJECT_ID"
        incoming_trace_context: ["CLOUD_TRACE_CONTEXT", "GRPC_TRACE_BIN"]
        outgoing_trace_context: ["CLOUD_TRACE_CONTEXT", "GRPC_TRACE_BIN"]

公开管理接口

有时,指标和跟踪记录数据不足以解决问题。您可能需要查看应用中 gRPC 库的配置或运行时状态。此类信息包括解析器信息、与对等端连接的状态、通道上的 RPC 统计信息,以及从 Traffic Director 收到的配置。

如需获取此类信息,gRPC 应用可以在特定端口上公开管理接口。然后,您可以查询应用以了解服务的配置方式和运行方式。在本部分中,您可以了解如何为采用各种受支持语言编写的应用配置管理接口。

我们建议您在应用中构建一个单独的 gRPC 服务器,以侦听为此用途而预留的端口。这样一来,即使数据端口因配置错误或网络问题而无法访问,您仍可以访问 gRPC 应用。我们建议您仅在 localhost 或 Unix 网域套接字上公开管理界面。

以下代码段展示了如何创建管理界面。

C++

在 C++ 中,使用以下代码创建管理界面:

#include <grpcpp/ext/admin_services.h>

grpc::ServerBuilder builder;
grpc::AddAdminServices(&builder);
builder.AddListeningPort(":50051", grpc::ServerCredentials(...));
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());

Go

在 Go 中,使用以下代码创建管理接口:

import "google.golang.org/grpc/admin"

lis, err := net.Listen("tcp", ":50051")
if err != nil {
        log.Fatalf("failed to listen: %v", err)
}
defer lis.Close()
grpcServer := grpc.NewServer(...opts)
cleanup, err := admin.Register(grpcServer)
if err != nil {
        log.Fatalf("failed to register admin services: %v", err)
}
defer cleanup()

if err := grpcServer.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
}

Java

在 Java 中,使用以下代码创建管理接口:

import io.grpc.services.AdminInterface;

server = ServerBuilder.forPort(50051)
        .useTransportSecurity(certChainFile, privateKeyFile)
        .addServices(AdminInterface.getStandardServices())
        .build()
        .start();
server.awaitTermination();

Python

在 Python 中,使用以下代码创建管理界面:

import grpc_admin

server = grpc.server(futures.ThreadPoolExecutor())
grpc_admin.add_admin_servicers(server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()

使用 SSH 连接到虚拟机

gRPC Wallet 示例已启用管理界面。您可以通过提供以下标志来更改管理界面端口:

 --admin-port=PORT

默认管理端口为 localhost:28881

如需调试您的 gRPC 应用,您可以使用 SSH 连接到其中一个传送 wallet-service 的虚拟机。这样您就可以使用 localhost 了。

# List the Wallet VMs
$ gcloud compute instances list --filter="zone:(us-central1-a)" --filter="name~'grpcwallet-wallet-v2'"
NAME                                       ZONE            MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP    EXTERNAL_IP     STATUS
grpcwallet-wallet-v2-mig-us-central1-ccl1  us-central1-a   n1-standard-1               10.240.0.38    35.223.42.98    RUNNING
grpcwallet-wallet-v2-mig-us-central1-k623  us-central1-a   n1-standard-1               10.240.0.112   35.188.133.75   RUNNING
# Pick one of the Wallet VMs to debug
$ gcloud compute ssh grpcwallet-wallet-v2-mig-us-central1-ccl1 --zone=us-central1-a

安装 grpcdebug 工具

如需访问管理接口,您需要一个可与 gRPC 应用中的管理服务通信的 gRPC 客户端。在以下示例中,您将使用名为 grpcdebug 的工具,您可以在运行 gRPC 应用的虚拟机或 pod 上下载并安装该工具。grpcdebug 的代码库位于 grpc-ecosystem/grpcdebug

支持的最低 Golang 版本为 1.12。官方 Golang 安装指南位于 Golang 网站上。如果您按照该指南为 wallet-service 创建 Linux 虚拟机,则可以使用以下命令安装 Golang 1.16:

sudo apt update && sudo apt install -y wget
wget https://golang.org/dl/go1.16.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.16.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
sudo ln -sf /usr/local/go/bin/go /usr/bin/go
go version
# go version go1.16.3 linux/amd64

使用以下命令安装 grpcdebug 工具:

go install -v github.com/grpc-ecosystem/grpcdebug@latest
export PATH=$PATH:$(go env GOPATH)/bin

您现在可以访问 grpcdebug 命令行界面了。帮助输出包含有关受支持命令的信息:

$ grpcdebug -h
grpcdebug is a gRPC service admin command-line interface

Usage:
  grpcdebug <target address> [flags]  <command>

Available Commands:
  channelz    Display gRPC states in human readable way.
  health      Check health status of the target service (default "").
  help        Help about any command
  xds         Fetch xDS related information.

Flags:
      --credential_file string        Sets the path of the credential file; used in [tls] mode
  -h, --help                          Help for grpcdebug
      --security string               Defines the type of credentials to use [tls, google-default, insecure] (default "insecure")
      --server_name_override string   Overrides the peer server name if non empty; used in [tls] mode
  -t, --timestamp                     Print timestamp as RFC 3339 instead of human readable strings
  -v, --verbose                       Print verbose information for debugging

如需获取有关特定命令的更多信息,请使用以下方法:

 grpcdebug <target address> [command] --help

使用 grpcdebug 工具调试应用

您可以使用 grpcdebug 工具调试应用。grpcdebug 工具提供类似于 ssh_config 的配置,支持别名、主机名重写和连接安全设置(不安全/TLS)。如需详细了解此高级功能,请参阅 grpcdebug/Connect&Security

以下部分介绍管理接口公开的服务以及如何访问这些服务。

使用 Channelz

Channelz 服务可提供应用的 gRPC 库中不同级别的连接相关运行时信息的权限。您可以使用此服务实时分析可能存在配置或网络相关问题的应用。以下示例假设您按照使用无代理 gRPC 服务配置高级流量管理中的说明部署了 gRPC Wallet 示例,并且提供了以下标志:

 --admin-port=PORT

按照验证配置中所述从测试客户端发送一些 RPC 后,可以使用以下命令访问 gRPC 服务的 Channelz 数据:

  1. 使用 SSH 连接到运行 wallet-service 的虚拟机。
  2. 设置 grpcdebug 以连接到正在运行的 gRPC 应用。

grpcdebug 的默认输出采用适合控制台的表格格式。如果提供 --json 标志,则输出编码为 JSON

grpcdebug channelz 命令用于从 Channelz 服务提取和显示调试信息。该命令同时适用于 gRPC 客户端和 gRPC 服务器。

对于 gRPC 客户端,命令 grpcdebug channelz channels 会提供现有渠道列表和一些基本信息:

$ grpcdebug localhost:28881 channelz channels
Channel ID   Target                               State     Calls(Started/Succeeded/Failed)   Created Time
1            xds:///account.grpcwallet.io:10080   READY     0/0/0                             59 seconds ago
2            trafficdirector.googleapis.com:443   READY     2/0/0                             59 seconds ago
4            xds:///stats.grpcwallet.io:10080     READY     0/0/0                             59 seconds ago

如果您需要详细了解特定渠道,可以使用 grpcdebug channelz channel [CHANNEL_ID] 来检查该渠道的详细信息。如果只有一个目标地址,则渠道标识符可以是渠道 ID 或目标地址。gRPC 渠道可以包含多个子渠道,而后者是基于 TCP 连接的 gRPC 抽象。

$ grpcdebug localhost:28881 channelz channel 2
Channel ID:        2
Target:            trafficdirector.googleapis.com:443
State:             READY
Calls Started:     2
Calls Succeeded:   0
Calls Failed:      0
Created Time:      10 minutes ago
---
Subchannel ID   Target                               State     Calls(Started/Succeeded/Failed)   CreatedTime
3               trafficdirector.googleapis.com:443   READY     2/0/0                             10 minutes ago
---
Severity   Time             Child Ref                      Description
CT_INFO    10 minutes ago                                  Channel Created
CT_INFO    10 minutes ago                                  parsed scheme: ""
CT_INFO    10 minutes ago                                  scheme "" not registered, fallback to default scheme
CT_INFO    10 minutes ago                                  ccResolverWrapper: sending update to cc: {[{trafficdirector.googleapis.com:443  <nil> 0 <nil>}] <nil> <nil>}
CT_INFO    10 minutes ago                                  Resolver state updated: {Addresses:[{Addr:trafficdirector.googleapis.com:443 ServerName: Attributes:<nil> Type:0 Metadata:<nil>}] ServiceConfig:<nil> Attributes:<nil>} (resolver returned new addresses)
CT_INFO    10 minutes ago                                  ClientConn switching balancer to "pick_first"
CT_INFO    10 minutes ago                                  Channel switches to new LB policy "pick_first"
CT_INFO    10 minutes ago   subchannel(subchannel_id:3 )   Subchannel(id:3) created
CT_INFO    10 minutes ago                                  Channel Connectivity change to CONNECTING
CT_INFO    10 minutes ago                                  Channel Connectivity change to READY

您还可以检查子渠道的详细信息:

$ grpcdebug localhost:28881 channelz subchannel 3
Subchannel ID:     3
Target:            trafficdirector.googleapis.com:443
State:             READY
Calls Started:     2
Calls Succeeded:   0
Calls Failed:      0
Created Time:      12 minutes ago
---
Socket ID   Local->Remote                           Streams(Started/Succeeded/Failed)   Messages(Sent/Received)
9           10.240.0.38:60338->142.250.125.95:443   2/0/0                               214/132

您可以检索有关 TCP 套接字的信息:

$ grpcdebug localhost:28881 channelz socket 9
Socket ID:                       9
Address:                         10.240.0.38:60338->142.250.125.95:443
Streams Started:                 2
Streams Succeeded:               0
Streams Failed:                  0
Messages Sent:                   226
Messages Received:               141
Keep Alives Sent:                0
Last Local Stream Created:       12 minutes ago
Last Remote Stream Created:      a long while ago
Last Message Sent Created:       8 seconds ago
Last Message Received Created:   8 seconds ago
Local Flow Control Window:       65535
Remote Flow Control Window:      966515
---
Socket Options Name   Value
SO_LINGER             [type.googleapis.com/grpc.channelz.v1.SocketOptionLinger]:{duration:{}}
SO_RCVTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}
SO_SNDTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}
TCP_INFO              [type.googleapis.com/grpc.channelz.v1.SocketOptionTcpInfo]:{tcpi_state:1  tcpi_options:7  tcpi_rto:204000  tcpi_ato:40000  tcpi_snd_mss:1408  tcpi_rcv_mss:1408  tcpi_last_data_sent:8212  tcpi_last_data_recv:8212  tcpi_last_ack_recv:8212  tcpi_pmtu:1460  tcpi_rcv_ssthresh:88288  tcpi_rtt:2400  tcpi_rttvar:3012  tcpi_snd_ssthresh:2147483647  tcpi_snd_cwnd:10  tcpi_advmss:1408  tcpi_reordering:3}
---
Security Model:   TLS
Standard Name:    TLS_AES_128_GCM_SHA256

在服务器端,您可以使用 Channelz 检查服务器应用的状态。例如,您可以使用 grpcdebug channelz servers 命令获取服务器列表:

$ grpcdebug localhost:28881 channelz servers
Server ID   Listen Addresses    Calls(Started/Succeeded/Failed)   Last Call Started
5           [127.0.0.1:28881]   9/8/0                             now
6           [[::]:50051]        159/159/0                         4 seconds ago

如需获取特定服务器的详细信息,请使用 grpcdebug channelz server 命令。您可以按照检查客户端套接字的方式检查服务器套接字。

$ grpcdebug localhost:28881 channelz server 6
Server Id:           6
Listen Addresses:    [[::]:50051]
Calls Started:       174
Calls Succeeded:     174
Calls Failed:        0
Last Call Started:   now
---
Socket ID   Local->Remote                            Streams(Started/Succeeded/Failed)   Messages(Sent/Received)
25          10.240.0.38:50051->130.211.1.39:44904    68/68/0                             68/68
26          10.240.0.38:50051->130.211.0.167:32768   54/54/0                             54/54
27          10.240.0.38:50051->130.211.0.22:32768    52/52/0                             52/52

使用客户端状态发现服务

客户端状态发现服务 (CSDS) API 是 xDS API 的一部分。在 gRPC 应用中,CSDS 服务可提供其从 Traffic Director 接收的配置(也称为 xDS 配置)的访问权限。这样,您就可以识别和解决网格中与配置相关的问题。

以下示例假设您按照使用无代理 gRPC 服务配置高级流量管理中的说明部署了 gRPC Wallet 示例。

要使用 CSDS 检查配置,请执行以下操作:

  1. 使用 SSH 连接到运行 wallet-service 的虚拟机。 按照使用 SSH 连接到虚拟机中的说明执行操作。
  2. 运行 grpcdebug 客户端。

如需获取配置状态的大致情况,请运行以下命令:

grpcdebug localhost:28881 xds status

您会看到如下所示的结果:

Name                                                                    Status    Version               Type                                                                 LastUpdated
account.grpcwallet.io:10080                                             ACKED     1618529574783547920   type.googleapis.com/envoy.config.listener.v3.Listener                3 seconds ago
stats.grpcwallet.io:10080                                               ACKED     1618529574783547920   type.googleapis.com/envoy.config.listener.v3.Listener                3 seconds ago
URL_MAP/830293263384_grpcwallet-url-map_0_account.grpcwallet.io:10080   ACKED     1618529574783547920   type.googleapis.com/envoy.config.route.v3.RouteConfiguration         3 seconds ago
URL_MAP/830293263384_grpcwallet-url-map_1_stats.grpcwallet.io:10080     ACKED     1618529574783547920   type.googleapis.com/envoy.config.route.v3.RouteConfiguration         3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3566964729007423588          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_7383783194368524341          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3363366193797120473          ACKED     1618529574783547920   type.googleapis.com/envoy.config.cluster.v3.Cluster                  3 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3566964729007423588          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago
cloud-internal-istio:cloud_mp_830293263384_3363366193797120473          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago
cloud-internal-istio:cloud_mp_830293263384_7383783194368524341          ACKED     86                    type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 seconds ago

您可以在 Envoy 代理的文档中找到配置状态的定义。简要来说,xDS 资源的状态为 REQUESTEDDOES_NOT_EXISTACKEDNACKED 之一。

如需获取原始 xDS 配置转储,请运行以下命令:

grpcdebug localhost:28881 xds config

您会看到 PerXdsConfig 对象的 JSON 列表:

{
  "config":  [
    {
      "node":  {
        "id":  "projects/830293263384/networks/default/nodes/6e98b038-6d75-4a4c-8d35-b0c7a8c9cdde",
        "cluster":  "cluster",
        "metadata":  {
          "INSTANCE_IP":  "10.240.0.38",
          "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER":  "830293263384",
          "TRAFFICDIRECTOR_NETWORK_NAME":  "default"
        },
        "locality":  {
          "zone":  "us-central1-a"
        },
        "userAgentName":  "gRPC Go",
        "userAgentVersion":  "1.37.0",
        "clientFeatures":  [
          "envoy.lb.does_not_support_overprovisioning"
        ]
      },
      "xdsConfig":  [
        {
          "listenerConfig":  {
            "versionInfo":  "1618529930989701137",
            "dynamicListeners":  [
              {
...

如果原始配置输出过于冗长,grpcdebug 可让您根据特定的 xDS 类型进行过滤。例如:

$ grpcdebug localhost:28881 xds config --type=cds
{
  "versionInfo":  "1618530076226619310",
  "dynamicActiveClusters":  [
    {
      "versionInfo":  "1618530076226619310",
      "cluster":  {
        "@type":  "type.googleapis.com/envoy.config.cluster.v3.Cluster",
        "name":  "cloud-internal-istio:cloud_mp_830293263384_7383783194368524341",
        "altStatName":  "/projects/830293263384/global/backendServices/grpcwallet-stats-service",
        "type":  "EDS",
        "edsClusterConfig":  {
          "edsConfig":  {
            "ads":  {},
            "initialFetchTimeout":  "15s",
...

您还可以同时转储几种 xDS 类型的配置:

$ grpcdebug localhost:28881 xds config --type=lds,eds
{
  "versionInfo":  "1618530076226619310",
  "dynamicListeners":  [...]
}
{
  "dynamicEndpointConfigs":  [...]
}

后续步骤