欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang使用OpenTelemetry實(shí)現(xiàn)跨服務(wù)全鏈路追蹤詳解

 更新時(shí)間:2023年09月03日 14:43:43   作者:莫大  
這篇文章主要為大家介紹了golang使用OpenTelemetry實(shí)現(xiàn)跨服務(wù)全鏈路追蹤詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

使用 OpenTelemetry 鏈路追蹤說明

  • 工作中常常會遇到需要查看服務(wù)調(diào)用關(guān)系,比如用戶請求了一個(gè)接口
  • 接口會調(diào)用其他grpc,http接口,或者內(nèi)部的方法
  • 這樣的調(diào)用鏈路,如果出現(xiàn)了問題,我們需要快速的定位問題,這時(shí)候就需要一個(gè)工具來幫助我們查看調(diào)用鏈路
  • OpenTelemetry就是這樣一個(gè)工具
  • 本文大概以:main 函數(shù)初始化 OpenTelemetry、啟動 http server、配置httpclient 請求服務(wù) 來進(jìn)行說明
  • 完整可執(zhí)行源碼在:opentelemetry-go 示例
  • 示例代碼已增加 grpc的鏈路追蹤

服務(wù)鏈路關(guān)系

關(guān)系圖

說明:

  • 用戶 請求 api1(echo server) 服務(wù)的 api1/bar
  • api1 調(diào)用 Grpc 服務(wù)
  • api1 調(diào)用 api2 (gin server) 服務(wù)的 api2/bar
  • api2 調(diào)用 api3 (echo server )服務(wù)的 api3/bar
  • api3 調(diào)用 內(nèi)部 調(diào)用方法 bar->bar2->bar3

安裝jaeger

  • 下載jaeger:我使用的是 jaeger-all-in-one
  • 啟動 jaeger: ~/tool/jaeger-1.31.0-linux-amd64/jaeger-all-in-one
  • 默認(rèn)查看面板 地址 http://localhost:16686/
  • tracer Batcher的地址,下面代碼會體現(xiàn): http://localhost:14268/api/traces

初始化 全局的 OpenTelemetry

這里openTelemetry 的exporter 以 jaeger 為例

var tracer = otel.Tracer("go-moda")
func InitJaegerProvider(jaegerUrl string, serviceName string) (func(ctx context.Context) error, error) {
    if jaegerUrl == "" {
        logger.Errorw("jaeger url is empty")
        return nil, nil
    }
    tracer = otel.Tracer(serviceName)
    exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(jaegerUrl)))
    if err != nil {
        return nil, err
    }
    tp := tracesdk.NewTracerProvider(
        tracesdk.WithBatcher(exp),
        tracesdk.WithResource(resource.NewSchemaless(
            semconv.ServiceNameKey.String(serviceName),
        )),
    )
    otel.SetTracerProvider(tp)
    // otel.SetTextMapPropagator(propagation.TraceContext{})
    b3Propagator := b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader))
    propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}, b3Propagator)
    otel.SetTextMapPropagator(propagator)
    return tp.Shutdown, nil
}

說明

  • jaegerUrl ,如果安裝的是 jaeger-all-in-one,則地址默認(rèn)為 http://localhost:14268/api/traces
  • serviceName 是服務(wù)名稱,這里我使用的是 api1,api2,api3
  • 增加 span 可以使用 tracer.Start(ctx, "spanName")

http服務(wù)鏈路追蹤

初始化了全局的 OpenTelemetry后,在當(dāng)前服務(wù)就可以使用 OpenTelemetry 的 tracer 進(jìn)行鏈路追蹤 比如

ctx, span := tracing.Start(ctx, "service.bar")
defer span.End()

但如果是跨服務(wù)進(jìn)行調(diào)用,比如 http server之間的調(diào)用,需要:

  • 對于 http client: 請求server的時(shí)候,將ctx(上下文) 注入到 請求頭中(req header) 中
  • 對于 http server: 在獲取http請求時(shí),解析 出請求頭 中的 parent trace 信息 這樣就可以實(shí)現(xiàn)跨服務(wù)鏈路追蹤

啟動 http服務(wù)開啟鏈路追蹤

http服務(wù),解析請求頭中的trace信息:echo 和 gin 都有成熟的的中間件,我們在初始化的時(shí)候,將中間件加入到服務(wù)中即可,下面是 echo 和 gin啟動服務(wù)的演示:

echo server 示例

import "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
e := echo.New()
e.Server.Use(otelecho.Middleware("moda"))

gin 舉例

import "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
ginEngine := gin.Default()
g.GetServer().Use(otelgin.Middleware("my-server"))

http client 鏈路追蹤

httpserver 啟動時(shí) 通過解析 請求頭 中的 parent trace 來進(jìn)行鏈路追蹤
那么在調(diào)用服務(wù)時(shí),就需要將上下文注入到 req header 中 下面是我個(gè)人封裝的 httpclient,可以參考:

package tracing
import (
    "bytes"
    "context"
    "encoding/json"
    "io"
    "io/ioutil"
    "net/http"
    "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
// 新增 options  http.Transport
type ClientOption struct {
    Transport *http.Transport
}
type ClientOptionFunc func(*ClientOption)
func WithClientTransport(transport *http.Transport) ClientOptionFunc {
    return func(option *ClientOption) {
        option.Transport = transport
    }
}
// CallAPI 為 http client 封裝,默認(rèn)使用 otelhttp.NewTransport(http.DefaultTransport)
func CallAPI(ctx context.Context, url string, method string, reqBody interface{}, option ...ClientOptionFunc) ([]byte, error) {
    clientOption := &ClientOption{}
    for _, o := range option {
        o(clientOption)
    }
    client := http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
    if clientOption.Transport != nil {
        client.Transport = otelhttp.NewTransport(clientOption.Transport)
    }
    var requestBody io.Reader
    if reqBody != nil {
        payload, err := json.Marshal(reqBody)
        if err != nil {
            return nil, err
        }
        requestBody = bytes.NewReader(payload)
    }
    req, err := http.NewRequestWithContext(ctx, method, url, requestBody)
    if err != nil {
        return nil, err
    }
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    resBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return resBody, nil
}

說明

  • 上面代碼中,主要是使用了 otelhttp.NewTransport(http.DefaultTransport) 將上下文注入到 req header 中
  • 調(diào)用服務(wù)時(shí),需要將上下文(ctx)傳入到 CallAPI 方法

調(diào)用服務(wù),查看鏈路關(guān)系

實(shí)戰(zhàn)代碼演示

跨服務(wù) 鏈路追蹤 大概說完 下面是運(yùn)行實(shí)戰(zhàn)代碼,分為普通運(yùn)行和docker 一鍵運(yùn)行

查看源碼位置:opentelemetry-go 示例

普通運(yùn)行

  • 示例文件:moda_tracing下 有四個(gè)目錄,分別是 api1_http,api2_http,api3_http,grpc 分別對應(yīng)三個(gè)api服務(wù) 一個(gè)grpc服務(wù)
  • 分別啟動三個(gè)服務(wù),進(jìn)入目錄 go run ./ -c ./conf.toml 即可啟動服務(wù)

docker 運(yùn)行

  • 進(jìn)入moda_tracing目錄
  • 執(zhí)行 make deploy,會同時(shí)啟動 jaeger,api1,api2,api3,grpc(mac 和 linux經(jīng)過試驗(yàn)可行,win如不行可使用第一種)

查看jaeger 鏈路

  • 根據(jù)上面鏈路關(guān)系,調(diào)用api1 等待調(diào)用完成: curl localhost:8081/api1/bar
  • 打開 jaeger 面板,查看鏈路關(guān)系圖,http://localhost:16686/

可以看到對應(yīng)的鏈路,在bar,bar2,bar3 刻意sleep 加了耗時(shí)也體現(xiàn)了出來

以上就是golang使用OpenTelemetry實(shí)現(xiàn)跨服務(wù)全鏈路追蹤詳解的詳細(xì)內(nèi)容,更多關(guān)于go OpenTelemetry全鏈路追蹤的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • gin框架Context如何獲取Get?Query?Param函數(shù)數(shù)據(jù)

    gin框架Context如何獲取Get?Query?Param函數(shù)數(shù)據(jù)

    這篇文章主要為大家介紹了gin框架Context?Get?Query?Param函數(shù)獲取數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go中的應(yīng)用配置管理詳解

    Go中的應(yīng)用配置管理詳解

    這篇文章主要為大家介紹了Go中的應(yīng)用配置管理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Go語言字符串拼接方式與性能比較分析

    Go語言字符串拼接方式與性能比較分析

    這篇文章主要為大家介紹了Go語言字符串拼接方式與性能比較示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 使用go進(jìn)行云存儲上傳實(shí)現(xiàn)實(shí)例

    使用go進(jìn)行云存儲上傳實(shí)現(xiàn)實(shí)例

    這篇文章主要為大家介紹了使用go進(jìn)行云存儲上傳實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2024-01-01
  • Golang在整潔架構(gòu)基礎(chǔ)上實(shí)現(xiàn)事務(wù)操作

    Golang在整潔架構(gòu)基礎(chǔ)上實(shí)現(xiàn)事務(wù)操作

    這篇文章在 go-kratos 官方的 layout 項(xiàng)目的整潔架構(gòu)基礎(chǔ)上,實(shí)現(xiàn)優(yōu)雅的數(shù)據(jù)庫事務(wù)操作,需要的朋友可以參考下
    2024-08-08
  • 從零開始學(xué)Golang的接口

    從零開始學(xué)Golang的接口

    本文主要介紹了從零開始學(xué)Golang的接口,原文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Golang 關(guān)于Gin框架請求參數(shù)的獲取方法

    Golang 關(guān)于Gin框架請求參數(shù)的獲取方法

    Gin是Go語言的Web框架,提供路由和中間件支持,本文介紹如何使用Gin獲取HTTP請求參數(shù),包括URLPath參數(shù)、URLQuery參數(shù)、HTTPBody參數(shù)和Header參數(shù),詳解直接獲取和綁定到結(jié)構(gòu)體兩種方法,幫助開發(fā)者高效處理Web請求
    2024-10-10
  • Golang搭建HTTP服務(wù)器

    Golang搭建HTTP服務(wù)器

    Golang是一種非常流行的編程語言,它的開發(fā)速度快,代碼運(yùn)行效率高等特點(diǎn)非常適合做Web應(yīng)用的開發(fā)。本文將介紹如何使用Golang搭建HTTP服務(wù)器,需要的朋友可以參考閱讀
    2023-04-04
  • Hugo?Config模塊構(gòu)建實(shí)現(xiàn)源碼剖析

    Hugo?Config模塊構(gòu)建實(shí)現(xiàn)源碼剖析

    這篇文章主要為大家介紹了Hugo?Config模塊構(gòu)建實(shí)現(xiàn)源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • golang類型斷言的實(shí)現(xiàn)示例

    golang類型斷言的實(shí)現(xiàn)示例

    在Go語言中,類型斷言用于從接口類型獲取其具體類型的值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10

最新評論