一、分布式鏈路追蹤發展簡介
1.1 分布式鏈路追蹤介紹
關于分布式鏈路追蹤的介紹,可以查看我前面的文章 微服務架構學習與思考(09):分布式鏈路追蹤系統-dapper論文學習(https://www.cnblogs.com/jiujuan/p/16097314.html) ,
這里的 OpenTelemetry 有一段發展歷程,
APM(Application Performance Monitoring) 和 Distributed Tracing(分布式跟蹤),后者是前者的子集,
微服務架構流行起來后,為了監控和定位微服務中請求鏈路過長導致的定位和監控問題,分布鏈路監控也蓬勃發展起來,出現了
很多有名的產品,比如:Jaeger,Pinpoint,Zipkin,Skywalking 等等,這里有個問題,就是每家都有自己的一套資料采集標準和SDK,
為了統一這些標準,國外的人們就創建了 OpenTracing 和 OpenCensus 2 個標準,最先出現的是 OpenTracing,為了統一標準,后來兩者合并為 OpenTelemetry,
1.2 OpenTracing
OpenTracing 制定了一套與平臺無關、廠商無關的協議標準,使得開發人員能夠方便的添加或更換底層APM的實作,
它是 CNCF 的專案,OpenTracing 協議的產品有 Jaeger、Zipkin 等等,
OpenTracing 資料模型
- Trace(s):
Trace(s) 在 OpenTracing 中是被 spans 隱式定義的,一個 trace 可以被認為是由一個或多個 span 組成的有向無環圖,
比如,下圖示例就表示一個 trace 由 8 個 span 組成,也就是一次鏈路追蹤由 8 個 span 組成:
單個 trace(鏈路) 中 span 之間的關系 [Span A] ←←←(the root span) | +------+------+ | | [Span B] [Span C] ←←←(Span C is a `ChildOf` Span A) | | [Span D] +---+-------+ | | [Span E] [Span F] >>> [Span G] >>> [Span H] ↑ ↑ ↑ (Span G `FollowsFrom` Span F)
用時間軸來可視化這次鏈路追蹤圖,更容易理解:
Temporal relationships between Spans in a single Trace
––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
[Span A···················································]
[Span B··············································]
[Span D··········································]
[Span C········································]
[Span E·······] [Span F··] [Span G··] [Span H··]
(來自:https://opentracing.io/specification/)
- Span:
Span 是一次鏈路追蹤里的基本組成元素,一個 Span 表示一個獨立作業單元,比如一次 http 請求,一次函式呼叫等,每個 span 里元素:
- An operation name,服務/操作名稱
- A start timestamp,開始時間
- A finish timestamp,結束時間
- Span Tags,key:value 資料形式,用戶自定義的標簽,主要用途是鏈路記錄資訊的查詢過濾,
- Span Logs,key:value 資料形式,主要用途是記錄某些事件和事件發生的時間,
- SpanContext 看下面解釋
- References,對 0 或 更多個相關 span 的參考(通過 SpanContext 來參考)
- SpanContext:
SpanContext 攜帶跨行程(跨服務)通信的資料,它的組成:
- 在系統中表示 span 的資訊,比如 span_id, trace_id,
- Baggage Items,為整條追蹤鏈路保存跨行程(跨服務)的資料,資料形式是 key:value
- References
多個 span 中的對應關系,OpenTracing 目前定義了 2 種關系:
ChildOf和FollowsFrom:
ChildOf,一個子 span 可能是父 span 的 ChildOf[-Parent Span---------] [-Child Span----] [-Parent Span--------------] [-Child Span A----] [-Child Span B----] [-Child Span C----] [-Child Span D---------------] [-Child Span E----]
FollowsFrom,一些父 span 不依賴任何的子 span[-Parent Span-] [-Child Span-] [-Parent Span--] [-Child Span-] [-Parent Span-] [-Child Span-](來自:https://opentracing.io/specification/)
1.3 OpenCensus
為什么又出現個 OpenCensus 這個專案?因為它有個好爹:google,要知道分布式跟蹤的基礎論文就是谷歌提出,
其實,剛開始它并不是要搶 OpenTracing 的飯碗,它只是為了把 Go 語言的 Metrics 采集、鏈路跟蹤與 Go 語言自帶的
profile 工具打通,統一用戶的使用方式,但是隨著專案發展,它也想把鏈路相關的統一一下,它不僅要做 Metrics 基礎指標監控,
還要做 OpenTracing 的老本行:分布式跟蹤,
1.4 OpenTracing 與 OpenCensus 對比
2 者功能對比


1.5 OpenTelemetry
這樣出現 2 個標準也不是個事啊,如是就出現了 OpenTelemetry,它把 2 者合并在一起了,
OpenTelemetry 的核心作業目前主要集中在 3 個部分:
- 規范的制定和協議的統一,規范包含資料傳輸、API 的規范,協議的統一包含:HTTP W3C 的標準支持及GRPC等框架的協議標準
- 多語言 SDK 的實作和集成,用戶可以使用 SDK 進行代碼自動注入和手動埋點,同時對其他三方庫(Log4j、LogBack等)進行集成支持;
- 資料收集系統的實作,當前是基于 OpenCensus Service 的收集系統,包括 Agent 和 Collector,
(1.4 1.5來自: https://github.com/open-telemetry/docs-cn)
OpenTelemetry 的最終形態就是實作 Metrics、Tracing、Logging 的融合,
OpenTelemetry 整體架構圖:

(來自:https://opentelemetry.io/docs/)
Tracing API 中幾個重要概念:
- TracerProvider:是 API 的入口點,提供了對 tracer 的訪問,在代碼里主要是創建一個 Tracer,一般是第三方分布式鏈路管理軟體提供具體實作,默認是一個空的 TracerProvider(""),雖然也創建 Tracer,但是內部不會執行資料流傳輸邏輯,
- Tracer:負責創建 span,一個 tracer 表示一次完整的追蹤鏈路,tracer 由一個或多個 span 組成,跟上面的 OpenTracing 資料模型很像,所以說是兩者合并,
- Span:一次鏈路追蹤操作里的基本操作元素,比如一次函式呼叫,一次 http 請求,
里面還有很多詳細介紹:https://opentelemetry.io/docs/reference/specification/trace/api/
還有一個資料采樣,https://www.cnblogs.com/jiujuan/p/16097314.html - 前面學習 dapper 論文的這篇文章有介紹,
小結:
一條鏈路追蹤資訊:
有一條鏈路 trace,它是由一個或多個 span 組成, span 里會記錄各種鏈路中的資訊,跨行程的資訊,各種 span 之間的關系,
使用哪種鏈路管理軟體,則由 traceprovider 來設定,可以是 Jaeger,Pinpoint,Zipkin,Skywalking 等等,
span 中的資訊收集到鏈路管理軟體,然后可以用圖來展示記錄的鏈路資訊和鏈路之間的關系,
二、jaeger 簡介
Jaeger 是受到 Dapper 和 OpenZipkin 啟發,是 Uber 開發的一款分布式鏈路追蹤系統,
它用于監控微服務和排查微服務中出現的故障,
jaeger 架構圖:

(來自:https://www.jaegertracing.io/docs/1.35/architecture/)
jaeger 安裝:
參考我前面文章 :https://www.cnblogs.com/jiujuan/p/13235748.html docker all-in-one 安裝
三、kratos 中鏈路追蹤使用
前面介紹了那么多,應該對 opentelemetry 大致有了一個了解,下面就在 kratos 中使用 opentelemetry,
這里使用 jaeger 作為鏈路追蹤的管理軟體,
go 1.17
go-kratos 2.2.1
jaeger 1.35
下面代碼來自 go-kratos 官方例子,
server 端
在 main.go 中,有 grpc server 和 http server,
第一步,設定 TraceProvider()
// set trace provider
func setTraceProvider(url string) error {
// create the jager exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil
}
// New trace provider
tp := tracesdk.NewTracerProvider(
// set the sampling rate based on the parent span to 100%, 設定采樣率 100%
tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
// always be sure to batch in production
tracesdk.WithBatcher(exp),
// Record information about this application in an Resource.
tracesdk.WithResource(resource.NewSchemaless(
semconv.ServiceNameKey.String(Name), // service name
attribute.String("env", Env), // environment
attribute.String("version", Version), // version
)),
)
otel.SetTracerProvider(tp)
return nil
}
第二步,grpc server 和 http server
err := setTraceProvider(url) // 呼叫上面的 setTraceProvider 函式
if err != nil {
log.Error(err)
}
// grpc server
grpcSrv := grpc.NewServer(
grpc.Address(":9000"),
grpc.Middleware(
middleware.Chain(
recovery.Recovery(),
tracing.Server(), // 設定 trace
logging.Server(logger),
),
),
)
// http server
httpSrv := http.NewServer(
http.Address(":8000"),
http.Middleware(
recovery.Recovery(),
tracing.Server(), // 設定 trace
logging.Server(logger),
),
)
client 端
grpc client 和 http client
grpc client:
// create grpc conn
// only for demo, use single instance in production env
conn, err := grpc.DialInsecure(ctx,
grpc.WithEndpoint("127.0.0.1:9000"),
grpc.WithMiddleware(
recovery.Recovery(),
tracing.Client(),
),
grpc.WithTimeout(2*time.Second),
// for tracing remote ip recording
grpc.WithOptions(grpcx.WithStatsHandler(&tracing.ClientHandler{})),
)
http client:
http.NewClient(ctx, http.WithMiddleware(
tracing.Client(
tracing.WithTracerProvider(s.tracer),
),
))
四、參考
- https://go-kratos.dev/docs/component/middleware/tracing/ 鏈路追蹤
- https://go-kratos.dev/blog/go-kratos-opentelemetry-practice/ 基于OpenTelemetry的鏈路追蹤
- https://opentracing.io/specification/ opentracing doc
- https://opentelemetry.io/docs/instrumentation opentelemetry doc
- https://opentelemetry.io/docs opentelemetry trace api
- https://opencensus.io/ opencensus 官網
- https://www.jaegertracing.io/docs/1.35/ jaeger doc
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/487414.html
標籤:Go
上一篇:IOS – OpenGL ES 影像漩渦 GPUImageSwirlFilter
下一篇:Guava中的封裝的Map操作
