無 Proxy gRPC 應用程式的可觀測性

微服務可觀測性工具可讓您檢測應用程式,以便在 Cloud MonitoringCloud LoggingCloud Trace 中收集及顯示從gRPC 工作負載 (包括 Cloud Service Mesh 中的 gRPC 工作負載) 擷取的遙測資料。 Google Cloud

gRPC 用戶端和伺服器會與 OpenCensus 整合,將指標和追蹤記錄匯出至各種後端,包括 Trace 和 Monitoring。您可以使用下列 gRPC 語言執行此操作:

  • C++
  • Go
  • Java

請參閱「微服務觀測功能總覽」,然後按照「設定微服務觀測功能」中的操作說明,為以下項目收集 gRPC 工作負載:

請按照本文件中的操作說明完成下列工作:

在 Trace 中查看追蹤記錄

完成設定程序後,您已檢測的 gRPC 用戶端和伺服器就會將追蹤記錄傳送至 Trace。 Google Cloud 控制台的「Trace Overview」(追蹤記錄總覽) 頁面會列出最近的追蹤記錄。您可以選取個別追蹤記錄,查看流量細目,類似於下一個章節所述。

追蹤與 Envoy Proxy 的相容性

如「Envoy 的觀測功能」一文所述,使用 Cloud Service Mesh 和 Envoy Proxy 將追蹤記錄匯出至 Trace,會使用 Envoy 的 OpenCensus 追蹤器設定,讓從無 Proxy gRPC 應用程式和 Envoy Proxy 匯出的追蹤記錄,在服務網格中完全相容。為了與無 Proxy 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 統計資料,以及從 Cloud Service Mesh 收到的設定。

為取得這類資訊,gRPC 應用程式可在特定通訊埠上公開管理介面。接著,您可以查詢應用程式,瞭解服務的設定方式和執行方式。本節提供如何設定以各個支援語言編寫的應用程式管理介面的操作說明。

建議您在應用程式中建構另一個 gRPC 伺服器,並讓該伺服器監聽專門用於此用途的通訊埠。這樣一來,即使因設定錯誤或網路問題而無法存取資料端口,您還是可以存取 gRPC 應用程式。建議您只在 localhost 或 Unix 網域 Socket 上公開管理介面。

以下程式碼片段說明如何建立管理員介面。

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 連線至 VM

gRPC Wallet 範例已啟用管理介面。您可以提供下列標記,變更管理介面連接埠:

 --admin-port=PORT

預設管理員通訊埠為 localhost:28881

如要對 gRPC 應用程式進行偵錯,您可以使用 SSH 連線至提供 wallet-service 的其中一個 VM。這樣一來,您就能存取 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 應用程式的 VM 或 Pod 上下載及安裝這項工具。grpcdebug 的存放區位於 grpc-ecosystem/grpcdebug

最低支援的 Golang 版本為 1.12。Golang 網站提供官方 Golang 安裝指南。如果您按照指南為 wallet-service 建立 Linux VM,可以使用下列指令安裝 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 程式庫中不同層級連線的執行階段資訊。您可以使用這項功能,針對可能有設定或網路相關問題的應用程式進行即時分析。以下範例假設您已按照「使用無 Proxy gRPC 服務設定進階流量管理」一文的操作說明,部署 gRPC Wallet 範例,並提供下列標記:

 --admin-port=PORT

從測試用戶端傳送一些 RPC 後 (如驗證設定所示),請使用下列指令存取 gRPC 服務的 Channelz 資料:

  1. 使用 SSH 連線至執行 wallet-service 的 VM。
  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 或目標位址 (如果只有一個目標位址) 都可以做為頻道 ID。gRPC 管道可包含多個子管道,這是 gRPC 在 TCP 連線之上的抽象概念。

$ 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

使用用戶端狀態探索服務

Client Status Discovery Service (CSDS) API 是 xDS API 的一部分。在 gRPC 應用程式中,CSDS 服務會提供從 Cloud Service Mesh 接收的設定 (也稱為 xDS 設定) 存取權。這可協助您找出並解決網格中的設定相關問題。

以下範例假設您已按照「透過無 Proxy gRPC 服務設定進階流量管理」一文中的指示,部署 gRPC Wallet 範例。

如何使用 CSDS 檢查設定:

  1. 使用 SSH 連線至執行 wallet-service 的 VM。請參閱「使用 SSH 連線至 VM」一節中的操作說明。
  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":  [...]
}

後續步驟