日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GRPC: 如何实现分布式日志跟踪?

發布時間:2024/8/23 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GRPC: 如何实现分布式日志跟踪? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介:?本文將介紹如何在 gRPC 分布式場景中,實現 API 的日志跟蹤。

介紹

本文將介紹如何在 gRPC 分布式場景中,實現 API 的日志追蹤。

什么是 API 日志追蹤?

一個 API 請求會跨多個微服務,我們希望通過一個唯一的 ID 檢索到整個鏈路的日志。

我們將會使用?rk-boot?來啟動 gRPC 服務。

請訪問如下地址獲取完整教程:

  • https://rkdev.info/cn
  • RK 文檔?(備用)

安裝

go get github.com/rookie-ninja/rk-boot

快速開始

rk-boot?默認集成了 grpc-gateway,并且會默認啟動。

我們會創建 /api/v1/greeter API 進行驗證,同時開啟 logging, meta 和 tracing 攔截器以達到目的。

1. 創建 api/v1/greeter.proto

syntax = "proto3";package api.v1;option go_package = "api/v1/greeter";service Greeter {rpc Greeter (GreeterRequest) returns (GreeterResponse) {} }message GreeterRequest {string name = 1; }message GreeterResponse {string message = 1; }

2. 創建 api/v1/gw_mapping.yaml

type: google.api.Service config_version: 3# Please refer google.api.Http in https://github.com/googleapis/googleapis/blob/master/google/api/http.proto file for details. http:rules:- selector: api.v1.Greeter.Greeterget: /api/v1/greeter

3. 創建 buf.yaml

version: v1beta1 name: github.com/rk-dev/rk-demo build:roots:- api

4. 創建 buf.gen.yaml

version: v1beta1 plugins:# protoc-gen-go needs to be installed, generate go files based on proto files- name: goout: api/genopt:- paths=source_relative# protoc-gen-go-grpc needs to be installed, generate grpc go files based on proto files- name: go-grpcout: api/genopt:- paths=source_relative- require_unimplemented_servers=false# protoc-gen-grpc-gateway needs to be installed, generate grpc-gateway go files based on proto files- name: grpc-gatewayout: api/genopt:- paths=source_relative- grpc_api_configuration=api/v1/gw_mapping.yaml# protoc-gen-openapiv2 needs to be installed, generate swagger config files based on proto files- name: openapiv2out: api/genopt:- grpc_api_configuration=api/v1/gw_mapping.yaml

5. 編譯 proto file

$ buf generate 如下的文件會被創建。 $ tree api/gen api/gen └── v1├── greeter.pb.go├── greeter.pb.gw.go├── greeter.swagger.json└── greeter_grpc.pb.go1 directory, 4 files

6. 創建 bootA.yaml & serverA.go

Server-A 監聽 1949 端口,并且發送請求給 Server-B。

我們通過 rkgrpcctx.InjectSpanToNewContext() 方法把 Tracing 信息注入到 Context 中,發送給 Server-B。

--- grpc:- name: greeter # Name of grpc entryport: 1949 # Port of grpc entryenabled: true # Enable grpc entryinterceptors:loggingZap:enabled: truemeta:enabled: truetracingTelemetry:enabled: true package mainimport ("context""demo/api/gen/v1""fmt""github.com/rookie-ninja/rk-boot""github.com/rookie-ninja/rk-grpc/interceptor/context""google.golang.org/grpc" )// Application entrance. func main() {// Create a new boot instance.boot := rkboot.NewBoot(rkboot.WithBootConfigPath("bootA.yaml"))// Get grpc entry with namegrpcEntry := boot.GetGrpcEntry("greeter")grpcEntry.AddRegFuncGrpc(registerGreeter)grpcEntry.AddRegFuncGw(greeter.RegisterGreeterHandlerFromEndpoint)// Bootstrapboot.Bootstrap(context.Background())// Wait for shutdown sigboot.WaitForShutdownSig(context.Background()) }func registerGreeter(server *grpc.Server) {greeter.RegisterGreeterServer(server, &GreeterServer{}) }type GreeterServer struct{}func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {// Call serverB at 2008 with grpc clientopts := []grpc.DialOption{grpc.WithBlock(),grpc.WithInsecure(),}conn, _ := grpc.Dial("localhost:2008", opts...)defer conn.Close()client := greeter.NewGreeterClient(conn)// Inject current trace information into contextnewCtx := rkgrpcctx.InjectSpanToNewContext(ctx)client.Greeter(newCtx, &greeter.GreeterRequest{Name: "A"})return &greeter.GreeterResponse{Message: fmt.Sprintf("Hello %s!", request.Name),}, nil }

7. 創建 bootB.yaml & serverB.go

Server-B 監聽 2008 端口。

--- grpc:- name: greeter # Name of grpc entryport: 2008 # Port of grpc entryenabled: true # Enable grpc entryinterceptors:loggingZap:enabled: truemeta:enabled: truetracingTelemetry:enabled: true package mainimport ("context""demo/api/gen/v1""fmt""github.com/rookie-ninja/rk-boot""google.golang.org/grpc" )// Application entrance. func main() {// Create a new boot instance.boot := rkboot.NewBoot(rkboot.WithBootConfigPath("bootB.yaml"))// Get grpc entry with namegrpcEntry := boot.GetGrpcEntry("greeter")grpcEntry.AddRegFuncGrpc(registerGreeterB)grpcEntry.AddRegFuncGw(greeter.RegisterGreeterHandlerFromEndpoint)// Bootstrapboot.Bootstrap(context.Background())// Wait for shutdown sigboot.WaitForShutdownSig(context.Background()) }func registerGreeterB(server *grpc.Server) {greeter.RegisterGreeterServer(server, &GreeterServerB{}) }type GreeterServerB struct{}func (server *GreeterServerB) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {return &greeter.GreeterResponse{Message: fmt.Sprintf("Hello %s!", request.Name),}, nil }

8. 文件夾結構

├── api │ ├── gen │ │ └── v1 │ │ ├── greeter.pb.go │ │ ├── greeter.pb.gw.go │ │ ├── greeter.swagger.json │ │ └── greeter_grpc.pb.go │ └── v1 │ ├── greeter.proto │ └── gw_mapping.yaml ├── bootA.yaml ├── bootB.yaml ├── buf.gen.yaml ├── buf.yaml ├── go.mod ├── go.sum ├── serverA.go └── serverB.go

9. 啟動 ServerA & ServerB

$ go run serverA.go $ go run serverB.go

10. 往 ServerA 發送請求

¥ curl "localhost:1949/api/v1/greeter?name=rk-dev"

11. 驗證日志

兩個服務的日志中,會有同樣的 traceId,不同的 requestId。

我們可以通過 grep traceId 來追蹤 RPC。

  • ServerA
------------------------------------------------------------------------ endTime=2021-10-20T00:02:21.739688+08:00 ... ids={"eventId":"0d145356-998a-4999-ab62-6f1b805274a0","requestId":"0d145356-998a-4999-ab62-6f1b805274a0","traceId":"c36a45eb076066df39fa407174012369"} ... operation=/api.v1.Greeter/Greeter resCode=OK eventStatus=Ended EOE
  • ServerB
------------------------------------------------------------------------ endTime=2021-10-20T00:02:21.739125+08:00 ... ids={"eventId":"8858a6eb-e953-42ad-bdc3-c466bbbd798e","requestId":"8858a6eb-e953-42ad-bdc3-c466bbbd798e","traceId":"c36a45eb076066df39fa407174012369"} ... operation=/api.v1.Greeter/Greeter resCode=OK eventStatus=Ended EOE

概念

當我們沒有使用例如 jaeger 調用鏈服務的時候,我們希望通過日志來追蹤分布式系統里的 RPC 請求。

rk-boot 的攔截器會通過 openTelemetry 庫來向日志寫入 traceId 來追蹤 RPC。

當啟動了日志攔截器,原數據攔截器,調用鏈攔截器的時候,攔截器會往日志里寫入如下三種 ID。

EventId

當啟動了日志攔截器,EventId 會自動生成。

--- grpc:- name: greeter # Name of grpc entryport: 1949 # Port of grpc entryenabled: true # Enable grpc entryinterceptors:loggingZap:enabled: true ------------------------------------------------------------------------ ... ids={"eventId":"cd617f0c-2d93-45e1-bef0-95c89972530d"} ...

RequestId

當啟動了日志攔截器和原數據攔截器,RequestId 和 EventId 會自動生成,并且這兩個 ID 會一致。

--- grpc:- name: greeter # Name of grpc entryport: 1949 # Port of grpc entryenabled: true # Enable grpc entryinterceptors:loggingZap:enabled: truemeta:enabled: true ------------------------------------------------------------------------ ... ids={"eventId":"8226ba9b-424e-4e19-ba63-d37ca69028b3","requestId":"8226ba9b-424e-4e19-ba63-d37ca69028b3"} ... 即使用戶覆蓋了 RequestId,EventId 也會保持一致。 rkgrpcctx.AddHeaderToClient(ctx, rkgrpcctx.RequestIdKey, "overridden-request-id") ------------------------------------------------------------------------ ... ids={"eventId":"overridden-request-id","requestId":"overridden-request-id"} ...

TraceId

當啟動了調用鏈攔截器,traceId 會自動生成。

--- grpc:- name: greeter # Name of grpc entryport: 1949 # Port of grpc entryenabled: true # Enable grpc entryinterceptors:loggingZap:enabled: truemeta:enabled: truetracingTelemetry:enabled: true ------------------------------------------------------------------------ ... ids={"eventId":"dd19cf9a-c7be-486c-b29d-7af777a78ebe","requestId":"dd19cf9a-c7be-486c-b29d-7af777a78ebe","traceId":"316a7b475ff500a76bfcd6147036951c"} ...

原文鏈接
本文為阿里云原創內容,未經允許不得轉載。?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的GRPC: 如何实现分布式日志跟踪?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。