Go微服務框架go-kratos實戰05:分散式鏈路追蹤 OpenTelemetry 使用

来源:https://www.cnblogs.com/jiujuan/archive/2022/06/07/16349519.html
-Advertisement-
Play Games

一、分散式鏈路追蹤發展簡介 1.1 分散式鏈路追蹤介紹 關於分散式鏈路追蹤的介紹,可以查看我前面的文章 微服務架構學習與思考(09):分散式鏈路追蹤系統-dapper論文學習(https://www.cnblogs.com/jiujuan/p/16097314.html) 。 這裡的 OpenTel ...


一、分散式鏈路追蹤發展簡介

1.1 分散式鏈路追蹤介紹

關於分散式鏈路追蹤的介紹,可以查看我前面的文章 微服務架構學習與思考(09):分散式鏈路追蹤系統-dapper論文學習(https://www.cnblogs.com/jiujuan/p/16097314.html) 。

這裡的 OpenTelemetry 有一段發展歷程。

APM(Application Performance Monitoring) 和 Distributed Tracing(分散式跟蹤),後者是前者的子集。

微服務架構流行起來後,為了監控和定位微服務中請求鏈路過長導致的定位和監控問題,分佈鏈路監控也蓬勃發展起來。出現了

很多有名的產品,比如:Jaeger,Pinpoint,Zipkin,Skywalking 等等。這裡有個問題,就是每家都有自己的一套數據採集標準和SDK。

為了統一這些標準,國外的人們就創建了 OpenTracingOpenCensus 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 種關係:ChildOfFollowsFrom

  • 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 者功能對比

image-20220605225353808

image-20220605224745472

1.5 OpenTelemetry

這樣出現 2 個標準也不是個事啊,如是就出現了 OpenTelemetry,它把 2 者合併在一起了。

OpenTelemetry 的核心工作目前主要集中在 3 個部分:

  1. 規範的制定和協議的統一,規範包含數據傳輸、API 的規範,協議的統一包含:HTTP W3C 的標準支持及GRPC等框架的協議標準
  2. 多語言 SDK 的實現和集成,用戶可以使用 SDK 進行代碼自動註入和手動埋點,同時對其他三方庫(Log4j、LogBack等)進行集成支持;
  3. 數據收集系統的實現,當前是基於 OpenCensus Service 的收集系統,包括 Agent 和 Collector。

(1.4 1.5來自: https://github.com/open-telemetry/docs-cn)

OpenTelemetry 的最終形態就是實現 Metrics、Tracing、Logging 的融合。

OpenTelemetry 整體架構圖:

image-20220606140340397

(來自: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 架構圖

image-20220606204357332

(來自: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),
    ),
))

四、參考

== just do it ==
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 剛剛看到一篇博客,說 stdbind 無法綁定正確的重載函數。這裡的問題並不是 stdbind 能力不足,而是將函數名傳遞給 std::bind 時編譯器無法取到這個函數的地址(也就是符號,編譯器會先解析成符號,鏈接器再替換為地址),因為有多個重載函數都是這個名字。核心問題是無法通過函數名取到想要的 ...
  • Spring Ioc源碼分析系列--自動註入迴圈依賴的處理 前言 前面的文章Spring Ioc源碼分析系列--Bean實例化過程(二)在講解到Spring創建bean出現迴圈依賴的時候並沒有深入去分析了,而是留到了這一篇去分析。為什麼要另起一篇,首先迴圈依賴是個很經典的問題,也是面試屢屢被問到的問 ...
  • 作者:lex-wu 來源:www.cnblogs.com/lex-wu/p/14610110.html 前言 最初是覺得我們打工人,在歷史的浪潮中,我們都被推著上岸。電子產品和移動互聯網,把我們的生活節奏大大提速了,所以很多人都忘記了生活和工作中的關係。 所以在深圳這個城市的各個街道上,都能看到忙忙 ...
  • 整型是我們日常生活中最常用到的基礎數據類型,看這篇文章之前,我想問: 我們真的像自己認為的那麼理解 Java 內的整型嗎? 也許看完本篇文章你就有自己的答案。 C 語言 提供瞭如下的整型 學習 Java 的整型之前,讓我們看看它的前輩——C 語言的實現。 讓我們更好地瞭解它的設計。 數據類型 占用字 ...
  • 成交量(volume)是投資中一個非常重要的變數,它是指在某一時段內具體的交易數,可以在分時圖中繪製,包括日線圖、周線圖、月線圖甚至是5分鐘、30分鐘、60分鐘圖中繪製。 股票市場成交量的變化反映了資金進出市場的情況,成交量是判斷市場走勢的重要指標。一般情況下,成交量大且價格上漲的股票,趨勢向好。成 ...
  • 有時候,我們將數據變換之後再繪圖,一方面,可以突出某些區域的數據;另一方面,變換之後可以更好的看出數據之間的關係。 matplotlib 提供了兩種變換數據的方式,一種是 Scale(縮放),一種是Projection(投影)。 Scale是對數據的一個維度進行變換,Projection則是對2個或 ...
  • 1、synchronized關鍵字簡介 synchronized是java中的一個關鍵字,在中文中為同步,也被稱之為'同步鎖',以此來達到多線程併發訪問時候的併發安全問題,可以用來修飾代碼塊、非靜態方法。靜態方法等; 修飾代碼塊時:給當前指定的對象加鎖 修飾非靜態方法時:作用於當前實例加鎖 修飾靜態 ...
  • 雙親委派機制:當某個類載入器準備載入一個.class位元組碼文件時,它首先將這個載入任務委派給上一級類載入器,上一級載入器再委派到更上一級類載入器,遞歸這個操作直到最頂級的類載入器。 一、類載入器的類別 在介紹Java的雙親委派機制的時候,不得不提ClassLoader(類載入器) 我們編譯的Java ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...