在實際應用中,你做了那么多 Server 端,寫了 N 個 RPC 方法。想看看方法的指標,卻無處下手?
本文將通過 gRPC + Opentracing + Zipkin 搭建一個分布式鏈路追蹤系統來實現查看整個系統的鏈路、性能等指標 🤓
Opentracing
是什么
OpenTracing 通過提供平台無關、廠商無關的API,使得開發人員能夠方便的添加(或更換)追蹤系統的實現
不過 OpenTracing 並不是標准。因為 CNCF 不是官方標准機構,但是它的目標是致力為分布式追蹤創建更標准的 API 和工具
名詞解釋
Trace
一個 trace 代表了一個事務或者流程在(分布式)系統中的執行過程
Span
一個 span 代表在分布式系統中完成的單個工作單元。也包含其他 span 的 “引用”,這允許將多個 spans 組合成一個完整的 Trace
每個 span 根據 OpenTracing 規范封裝以下內容:
-
操作名稱
-
開始時間和結束時間
-
key:value span Tags
-
key:value span Logs
-
SpanContext
Tags
Span tags(跨度標簽)可以理解為用戶自定義的 Span 注釋。便於查詢、過濾和理解跟蹤數據
Logs
Span logs(跨度日志)可以記錄 Span 內特定時間或事件的日志信息。主要用於捕獲特定 Span 的日志信息以及應用程序本身的其他調試或信息輸出
SpanContext
SpanContext 代表跨越進程邊界,傳遞到子級 Span 的狀態。常在追蹤示意圖中創建上下文時使用
Baggage Items
一個案例
圖中可以看到以下內容:
-
執行時間的上下文
-
服務間的層次關系
-
服務間串行或並行調用鏈
結合以上信息,在實際場景中我們可以通過整個系統的調用鏈的上下文、性能等指標信息,一下子就能夠發現系統的痛點在哪兒
Zipkin
是什么
Zipkin 是分布式追蹤系統。它的作用是收集解決微服務架構中的延遲問題所需的時序數據。它管理這些數據的收集和查找
Zipkin 的設計基於 Google Dapper 論文。
運行
docker run -d -p 9411:9411 openzipkin/zipkin
go-grpc-example
├── LICENSE
├── README.md
├── client
│ ├── ...
│ ├── simple_zipkin_client
├── conf
├── pkg
├── proto
├── server
│ ├── ...
│ ├── simple_zipkin_server
└── vendor
$ go get -u github.com/openzipkin/zipkin-go-opentracing
$ go get -u github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc
package main
import (
"context"
"log"
"net"
"github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
zipkin "github.com/openzipkin/zipkin-go-opentracing"
"google.golang.org/grpc"
"github.com/EDDYCJY/go-grpc-example/pkg/gtls"
pb "github.com/EDDYCJY/go-grpc-example/proto"
)
type SearchService struct{}
func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
return &pb.SearchResponse{Response: r.GetRequest() + " Server"}, nil
}
const (
PORT = "9005"
SERVICE_NAME = "simple_zipkin_server"
ZIPKIN_HTTP_ENDPOINT = "http://127.0.0.1:9411/api/v1/spans"
ZIPKIN_RECORDER_HOST_PORT = "127.0.0.1:9000"
)
func main() {
collector, err := zipkin.NewHTTPCollector(ZIPKIN_HTTP_ENDPOINT)
if err != nil {
log.Fatalf("zipkin.NewHTTPCollector err: %v", err)
}
recorder := zipkin.NewRecorder(collector, true, ZIPKIN_RECORDER_HOST_PORT, SERVICE_NAME)
tracer, err := zipkin.NewTracer(
recorder, zipkin.ClientServerSameSpan(false),
)
if err != nil {
log.Fatalf("zipkin.NewTracer err: %v", err)
}
tlsServer := gtls.Server{
CaFile: "../../conf/ca.pem",
CertFile: "../../conf/server/server.pem",
KeyFile: "../../conf/server/server.key",
}
c, err := tlsServer.GetCredentialsByCA()
if err != nil {
log.Fatalf("GetTLSCredentialsByCA err: %v", err)
}
opts := []grpc.ServerOption{
grpc.Creds(c),
grpc_middleware.WithUnaryServerChain(
otgrpc.OpenTracingServerInterceptor(tracer, otgrpc.LogPayloads()),
),
}
...
}
func main() {
// the same as zipkin server
// ...
conn, err := grpc.Dial(":"+PORT, grpc.WithTransportCredentials(c),
grpc.WithUnaryInterceptor(
otgrpc.OpenTracingClientInterceptor(tracer, otgrpc.LogPayloads()),
))
...
}
本系列示例代碼
參考
希望你通過本章節的介紹和學習,能夠了解其概念和搭建且應用一個追蹤系統 😄
在多服務下的架構下,串行、並行、服務套服務是一個非常常見的情況,用常規的方案往往很難發現問題在哪里(成本太大)。而這種情況就是分布式追蹤系統大展拳腳的機會了
總結
來,自己實踐一下
復雜點
啟動 Server.go,執行 Client.go。查看 http://127.0.0.1:9411/zipkin/ 的示意圖:
驗證
其他方面,與 Server 端是一致的,先初始化 Zipkin,再增加 Client 端特需的攔截器。就可以完成基礎工作啦
(2)查看 context.Context 中的上下文關系,若存在父級 Span 則創建一個 ChildOf 引用,得到一個子 Span
(1)OpenTracing SpanContext 注入 gRPC Metadata
-
otgrpc.OpenTracingClientInterceptor:返回 grpc.UnaryClientInterceptor。該攔截器的核心功能在於:
Client
總的來講,就是初始化 Zipkin,其又包含收集器、記錄器、跟蹤器。再利用攔截器在 Server 端實現 SpanContext、Payload 的雙向讀取和管理
-
zipkin.NewHTTPCollector:創建一個 Zipkin HTTP 后端收集器
-
zipkin.NewRecorder:創建一個基於 Zipkin 收集器的記錄器
-
zipkin.NewTracer:創建一個 OpenTracing 跟蹤器(兼容 Zipkin Tracer)
-
otgrpc.OpenTracingClientInterceptor:返回 grpc.UnaryServerInterceptor,不同點在於該攔截器會在 gRPC Metadata 中查找 OpenTracing SpanContext。如果找到則為該服務的 Span Context 的子節點
-
otgrpc.LogPayloads:設置並返回 Option。作用是讓 OpenTracing 在雙向方向上記錄應用程序的有效載荷(payload)
Server
gRPC
安裝
新建 simple_zipkin_client、simple_zipkin_server 目錄,目錄結構如下:
目錄結構
接下來實現 gRPC 通過 Opentracing 標准 API 對接 Zipkin,再通過 Zipkin 去查看數據
-
了解 Opentracing 是什么
-
搭建 Zipkin 提供分布式追蹤系統的功能
在前面的小節中,我們做了以下准備工作:
gRPC + Opentracing + Zipkin
訪問 http://127.0.0.1:9411/zipkin/ 檢查 Zipkin 是否運行正常
驗證
其他方法安裝參見:https://github.com/openzipkin/zipkin