真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Go微服務(wù)框架go-kratos實(shí)戰(zhàn)學(xué)習(xí)05:分布式鏈路追蹤 OpenTelemetry 使用

一、分布式鏈路追蹤發(fā)展簡(jiǎn)介

1.1 分布式鏈路追蹤介紹

關(guān)于分布式鏈路追蹤的介紹,可以查看我前面的文章 微服務(wù)架構(gòu)學(xué)習(xí)與思考(09):分布式鏈路追蹤系統(tǒng)-dapper論文學(xué)習(xí)(https://www.cnblogs.com/jiujuan/p/.html) 。

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)龍華,十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):028-86922220

這里的 OpenTelemetry 有一段發(fā)展歷程。

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

微服務(wù)架構(gòu)流行起來(lái)后,為了監(jiān)控和定位微服務(wù)中請(qǐng)求鏈路過(guò)長(zhǎng)導(dǎo)致的定位和監(jiān)控問(wèn)題,分布鏈路監(jiān)控也蓬勃發(fā)展起來(lái)。出現(xiàn)了

很多有名的產(chǎn)品,比如:Jaeger,Pinpoint,Zipkin,Skywalking 等等。這里有個(gè)問(wèn)題,就是每家都有自己的一套數(shù)據(jù)采集標(biāo)準(zhǔn)和SDK。

為了統(tǒng)一這些標(biāo)準(zhǔn),國(guó)外的人們就創(chuàng)建了 OpenTracing 和 OpenCensus 2 個(gè)標(biāo)準(zhǔn)。最先出現(xiàn)的是 OpenTracing。為了統(tǒng)一標(biāo)準(zhǔn),后來(lái)兩者合并為 OpenTelemetry。

1.2 OpenTracing

OpenTracing 制定了一套與平臺(tái)無(wú)關(guān)、廠商無(wú)關(guān)的協(xié)議標(biāo)準(zhǔn),使得開(kāi)發(fā)人員能夠方便的添加或更換底層APM的實(shí)現(xiàn)。

它是 CNCF 的項(xiàng)目。OpenTracing 協(xié)議的產(chǎn)品有 Jaeger、Zipkin 等等。

OpenTracing 數(shù)據(jù)模型

  • Trace(s):

Trace(s) 在 OpenTracing 中是被 spans 隱式定義的。一個(gè) trace 可以被認(rèn)為是由一個(gè)或多個(gè) span 組成的有向無(wú)環(huán)圖。

比如,下圖示例就表示一個(gè) trace 由 8 個(gè) span 組成,也就是一次鏈路追蹤由 8 個(gè) span 組成:

單個(gè) trace(鏈路) 中 span 之間的關(guān)系


        [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)

用時(shí)間軸來(lái)可視化這次鏈路追蹤圖,更容易理解:

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··]

(來(lái)自:https://opentracing.io/specification/)

  • Span:

Span 是一次鏈路追蹤里的基本組成元素,一個(gè) Span 表示一個(gè)獨(dú)立工作單元,比如一次 http 請(qǐng)求,一次函數(shù)調(diào)用等。每個(gè) span 里元素:

  • An operation name,服務(wù)/操作名稱(chēng)
  • A start timestamp,開(kāi)始時(shí)間
  • A finish timestamp,結(jié)束時(shí)間
  • Span Tags,key:value 數(shù)據(jù)形式,用戶自定義的標(biāo)簽,主要用途是鏈路記錄信息的查詢(xún)過(guò)濾。
  • Span Logs,key:value 數(shù)據(jù)形式,主要用途是記錄某些事件和事件發(fā)生的時(shí)間。
  • SpanContext 看下面解釋
  • References,對(duì) 0 或 更多個(gè)相關(guān) span 的引用(通過(guò) SpanContext 來(lái)引用)
  • SpanContext:

SpanContext 攜帶跨進(jìn)程(跨服務(wù))通信的數(shù)據(jù)。它的組成:

  • 在系統(tǒng)中表示 span 的信息。比如 span_id, trace_id。
  • Baggage Items,為整條追蹤鏈路保存跨進(jìn)程(跨服務(wù))的數(shù)據(jù),數(shù)據(jù)形式是 key:value
  • References

多個(gè) span 中的對(duì)應(yīng)關(guān)系。OpenTracing 目前定義了 2 種關(guān)系:ChildOfFollowsFrom

  • ChildOf,一個(gè)子 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 不依賴(lài)任何的子 span
    [-Parent Span-]  [-Child Span-]


    [-Parent Span--]
     [-Child Span-]


    [-Parent Span-]
                [-Child Span-]

(來(lái)自:https://opentracing.io/specification/)

1.3 OpenCensus

為什么又出現(xiàn)個(gè) OpenCensus 這個(gè)項(xiàng)目?因?yàn)樗袀€(gè)好爹:google。要知道分布式跟蹤的基礎(chǔ)論文就是谷歌提出。

其實(shí),剛開(kāi)始它并不是要搶 OpenTracing 的飯碗,它只是為了把 Go 語(yǔ)言的 Metrics 采集、鏈路跟蹤與 Go 語(yǔ)言自帶的

profile 工具打通,統(tǒng)一用戶的使用方式。但是隨著項(xiàng)目發(fā)展,它也想把鏈路相關(guān)的統(tǒng)一一下。它不僅要做 Metrics 基礎(chǔ)指標(biāo)監(jiān)控,

還要做 OpenTracing 的老本行:分布式跟蹤。

1.4 OpenTracing 與 OpenCensus 對(duì)比

2 者功能對(duì)比

1.5 OpenTelemetry

這樣出現(xiàn) 2 個(gè)標(biāo)準(zhǔn)也不是個(gè)事啊,如是就出現(xiàn)了 OpenTelemetry,它把 2 者合并在一起了。

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

  1. 規(guī)范的制定和協(xié)議的統(tǒng)一,規(guī)范包含數(shù)據(jù)傳輸、API 的規(guī)范,協(xié)議的統(tǒng)一包含:HTTP W3C 的標(biāo)準(zhǔn)支持及GRPC等框架的協(xié)議標(biāo)準(zhǔn)
  2. 多語(yǔ)言 SDK 的實(shí)現(xiàn)和集成,用戶可以使用 SDK 進(jìn)行代碼自動(dòng)注入和手動(dòng)埋點(diǎn),同時(shí)對(duì)其他三方庫(kù)(Log4j、LogBack等)進(jìn)行集成支持;
  3. 數(shù)據(jù)收集系統(tǒng)的實(shí)現(xiàn),當(dāng)前是基于 OpenCensus Service 的收集系統(tǒng),包括 Agent 和 Collector。

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

OpenTelemetry 的最終形態(tài)就是實(shí)現(xiàn) Metrics、Tracing、Logging 的融合。

OpenTelemetry 整體架構(gòu)圖:

(來(lái)自:https://opentelemetry.io/docs/)

Tracing API 中幾個(gè)重要概念:

  • TracerProvider:是 API 的入口點(diǎn),提供了對(duì) tracer 的訪問(wèn)。在代碼里主要是創(chuàng)建一個(gè) Tracer,一般是第三方分布式鏈路管理軟件提供具體實(shí)現(xiàn)。默認(rèn)是一個(gè)空的 TracerProvider(""),雖然也創(chuàng)建 Tracer,但是內(nèi)部不會(huì)執(zhí)行數(shù)據(jù)流傳輸邏輯。
  • Tracer:負(fù)責(zé)創(chuàng)建 span,一個(gè) tracer 表示一次完整的追蹤鏈路。tracer 由一個(gè)或多個(gè) span 組成。跟上面的 OpenTracing 數(shù)據(jù)模型很像,所以說(shuō)是兩者合并。
  • Span:一次鏈路追蹤操作里的基本操作元素。比如一次函數(shù)調(diào)用,一次 http 請(qǐng)求。

里面還有很多詳細(xì)介紹:https://opentelemetry.io/docs/reference/specification/trace/api/

還有一個(gè)數(shù)據(jù)采樣,https://www.cnblogs.com/jiujuan/p/.html - 前面學(xué)習(xí) dapper 論文的這篇文章有介紹。

小結(jié):

一條鏈路追蹤信息:

有一條鏈路 trace,它是由一個(gè)或多個(gè) span 組成, span 里會(huì)記錄各種鏈路中的信息,跨進(jìn)程的信息,各種 span 之間的關(guān)系。

使用哪種鏈路管理軟件,則由 traceprovider 來(lái)設(shè)置??梢允?Jaeger,Pinpoint,Zipkin,Skywalking 等等。

span 中的信息收集到鏈路管理軟件,然后可以用圖來(lái)展示記錄的鏈路信息和鏈路之間的關(guān)系。

二、jaeger 簡(jiǎn)介

Jaeger 是受到 Dapper 和 OpenZipkin 啟發(fā),是 Uber 開(kāi)發(fā)的一款分布式鏈路追蹤系統(tǒng)。

它用于監(jiān)控微服務(wù)和排查微服務(wù)中出現(xiàn)的故障。

jaeger 架構(gòu)圖

(來(lái)自:https://www.jaegertracing.io/docs/1.35/architecture/)

jaeger 安裝:

參考我前面文章 :https://www.cnblogs.com/jiujuan/p/.html docker all-in-one 安裝

三、kratos 中鏈路追蹤使用代碼

前面介紹了那么多,應(yīng)該對(duì) opentelemetry 大致有了一個(gè)了解。下面就在 kratos 中使用 opentelemetry。

這里使用 jaeger 作為鏈路追蹤的管理軟件。

go 1.17

go-kratos 2.2.1

jaeger 1.35

下面代碼來(lái)自 go-kratos 官方例子。

server 端

在 main.go 中,有 grpc server 和 http server。

第一步,設(shè)置 TraceProvider()

// get trace provider
func tracerProvider(url string) (*tracesdk.TracerProvider, error) {
	// create the jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		return nil, err
	}

	// New trace provider
	tp := tracesdk.NewTracerProvider(
		tracesdk.WithSampler(tracesdk.AlwaysSample()),
		// always be sure to batch in production
		tracesdk.WithBatcher(exp),
		// Record information about this application in an Resource.
		tracesdk.WithResource(
			resource.NewWithAttributes(
				semconv.SchemaURL,
				semconv.ServiceNameKey.String(Name), // service name,實(shí)例名稱(chēng)
				attribute.String("env", Env),        // environment
				attribute.String("ID", Version),     // version
			)),
	)
	return tp, nil
}

第二步,grpc server

url := "http://jaeger:/api/traces"
if os.Getenv("jaeger_url") != "" {
    url = os.Getenv("jeager_url")
}

tp, err := tracerProvider(url) // tracer provider
if err != nil {
    log.Error(err)
}

s := &server{}

// grpc server
grpcSrv := grpc.NewServer(
    grpc.Address(":9000"),
    grpc.Middleware(
        middleware.Chain(
            recovery.Recovery(),
            tracing.Server(tracing.WithTracerProvider(tp)), //設(shè)置trace,傳入 trace provider
            logging.Server(logger),
        ),
    ),
)

第三步,http server

func main() {
	logger := log.NewStdLogger(os.Stdout)
	log := log.NewHelper(logger)

	tp, err := tracerProvider("http://jaeger:/api/traces")
	if err != nil {
		log.Error(err)
	}

	httpSrv := http.NewServer(
		http.Address(":8080"),
		http.Middleware(
			middleware.Chain(
				recovery.Recovery(),
				// Configuring tracing middleware
				tracing.Server(
					tracing.WithTracerProvider(tp), // 提供 trace provider
				),
				logging.Server(logger),
			),
		),
	)
	s := &server{}
	pb.RegisterUserHTTPServer(httpSrv, s)

	app := kratos.New(
		kratos.Name(Name),
		kratos.Server(
			httpSrv,
		),
	)

	if err := app.Run(); err != nil {
		log.Error(err)
	}
}

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(middleware.Chain(
	   tracing.Client( //trace client
		   tracing.WithTracerProvider(s.tracer),
	   ),
	   recovery.Recovery(),
   )),
   grpc.WithTimeout(time.Second*2),
  )
if err != nil {
    return nil, err
}

http client:

http.NewClient(ctx, http.WithMiddleware(
    tracing.Client(
        tracing.WithTracerProvider(s.tracer),
    ),
))

四、在student項(xiàng)目里使用鏈路追蹤

在前面的 go-kratos gorm 練習(xí)項(xiàng)目中加入鏈路追蹤。
https://github.com/jiujuan/go-kratos-demos/tree/master/student。

4.1 編寫(xiě)代碼

第一步,在 internal/server 下新建 pkg/tracer 文件夾,tracer.go 程序

把 tracer.go 作為一個(gè)獨(dú)立文件

package tracer

import (
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
)

type Conf struct {
	Name string
	Env  string
	Ver  string
	Url  string
}

func NewConf(name, env, ver, url string) *Conf {
	return &Conf{
		Name: name,
		Env:  env,
		Ver:  ver,
		Url:  url,
	}
}

func (c *Conf) TracerProvider() (*tracesdk.TracerProvider, error) {
	exp, err := jaeger.New(
		jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(c.Url)),
	)
	if err != nil {
		return nil, err
	}

	tp := tracesdk.NewTracerProvider(
		tracesdk.WithSampler(tracesdk.AlwaysSample()),
		tracesdk.WithBatcher(exp),
		tracesdk.WithResource(
			resource.NewWithAttributes(
				semconv.SchemaURL,
				semconv.ServiceNameKey.String(c.Name),
				attribute.String("env", c.Env),
				attribute.String("ver", c.Ver),
			)),
	)
	return tp, nil
}

第二步,在 internal/server/grpc.go:NewGRPCServer() 函數(shù)加入鏈路追蹤代碼:

var opts = []grpc.ServerOption{
	grpc.Middleware(
		recovery.Recovery(),
		tracing.Server(), // 鏈路追蹤
	),
}

第三步,在 internal/server/grpc.go:NewHTTPServer() 函數(shù)加入鏈路追蹤代碼:

var opts = []http.ServerOption{
	http.Middleware(
		recovery.Recovery(),
		tracing.Server(), // 鏈路追蹤
	),
}

第四步,在 cmd/student/main.go 加入如下代碼:

// 配置,啟動(dòng)鏈路追蹤
url := "http://192.168.0.103:/api/traces"
Name = "kratos.service.student"
id = "kratos.id.student.1"
Version = "test-V0.0.1"
traceconf := tracer.NewConf(Name, id, Version, url)
tp, _ := traceconf.TracerProvider()
otel.SetTracerProvider(tp) // 為全局鏈路追蹤

上面這段程序可以用 wire 配置程序。

完整代碼地址:完整代碼地址:https://github.com/jiujuan/go-kratos-demos/tree/master/student

4.2 測(cè)試

請(qǐng)先自行安裝 jaeger。

可以用 docker all-in-one 快速安裝,詳細(xì)命令請(qǐng)參考:https://www.cnblogs.com/jiujuan/p/.html

第一步,啟動(dòng)kratos服務(wù)

$ cd cmd/student
$ kratos run
INFO msg=config loaded: config.yaml format: yaml
INFO msg=[gRPC] server listening on: [::]:9000
INFO msg=[HTTP] server listening on: 127.0.0.1:8080

第二步,使用 curlie - https://github.com/rs/curlie 測(cè)試:

$ curlie  http://127.0.0.1:8080/student/3
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 34

{
    "name": "jimmy",
    "status": 0,
    "id": 3
}

第三步:打開(kāi) jaeger web ui 查看結(jié)果

http://192.168.0.103:/search

完整代碼地址:完整代碼地址:https://github.com/jiujuan/go-kratos-demos/tree/master/student

五、參考

  • 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 官網(wǎng)
  • https://www.jaegertracing.io/docs/1.35/ jaeger doc

當(dāng)前文章:Go微服務(wù)框架go-kratos實(shí)戰(zhàn)學(xué)習(xí)05:分布式鏈路追蹤 OpenTelemetry 使用
URL網(wǎng)址:http://weahome.cn/article/dsoichi.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部