日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ajax请求是宏任务还是微任务_微服务-如何解决链路追踪问题

發(fā)布時(shí)間:2023/12/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ajax请求是宏任务还是微任务_微服务-如何解决链路追踪问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、鏈路追蹤

微服務(wù)架構(gòu)是將單個(gè)應(yīng)用程序被劃分成各種小而連接的服務(wù),每一個(gè)服務(wù)完成一個(gè)單一的業(yè)務(wù)功能,相互之間保持獨(dú)立和解耦,每個(gè)服務(wù)都可以獨(dú)立演進(jìn)。相對(duì)于傳統(tǒng)的單體服務(wù),微服務(wù)具有隔離性、技術(shù)異構(gòu)性、可擴(kuò)展性以及簡(jiǎn)化部署等優(yōu)點(diǎn)。

? 同樣的,微服務(wù)架構(gòu)在帶來(lái)諸多益處的同時(shí),也為系統(tǒng)增加了不少?gòu)?fù)雜性。它作為一種分布式服務(wù),通常部署于由不同的數(shù)據(jù)中心、不同的服務(wù)器組成的集群上。而且,同一個(gè)微服務(wù)系統(tǒng)可能是由不同的團(tuán)隊(duì)、不同的語(yǔ)言開(kāi)發(fā)而成。通常一個(gè)應(yīng)用由多個(gè)微服務(wù)組成,微服務(wù)之間的數(shù)據(jù)交互需要通過(guò)遠(yuǎn)過(guò)程調(diào)用的方式完成,所以在一個(gè)由眾多微服務(wù)構(gòu)成的系統(tǒng)中,請(qǐng)求需要在各服務(wù)之間流轉(zhuǎn),調(diào)用鏈路錯(cuò)綜復(fù)雜,一旦出現(xiàn)問(wèn)題,是很難進(jìn)行問(wèn)題定位和追查異常的。

? 鏈路追蹤系統(tǒng)就是為解決上述問(wèn)題而產(chǎn)生的,它用來(lái)追蹤每一個(gè)請(qǐng)求的完整調(diào)用鏈路,記錄從請(qǐng)求開(kāi)始到請(qǐng)求結(jié)束期間調(diào)用的任務(wù)名稱、耗時(shí)、標(biāo)簽數(shù)據(jù)以及日志信息,并通過(guò)可視化的界面進(jìn)行分析和展示,來(lái)幫助技術(shù)人員準(zhǔn)確地定位異常服務(wù)、發(fā)現(xiàn)性能瓶頸、梳理調(diào)用鏈路以及預(yù)估系統(tǒng)容量。

? 鏈路追蹤系統(tǒng)的理論模型幾乎都借鑒了 Google 的一篇論文”Dapper, a Large-Scale Distributed Systems Tracing Infrastructure”,典型產(chǎn)品有Uber jaeger、Twitter zipkin、淘寶鷹眼等。這些產(chǎn)品的實(shí)現(xiàn)方式雖然不盡相同,但核心步驟一般都有三個(gè):數(shù)據(jù)采集、數(shù)據(jù)存儲(chǔ)和查詢展示。

? 鏈路追蹤系統(tǒng)第一步,也是最基本的工作就是數(shù)據(jù)采集。在這個(gè)過(guò)程中,鏈路追蹤系統(tǒng)需要侵入用戶代碼進(jìn)行埋點(diǎn),用于收集追蹤數(shù)據(jù)。但是由于不同的鏈路追蹤系統(tǒng)的API互不兼容,所以埋點(diǎn)代碼寫法各異,導(dǎo)致用戶在切換不同鏈路追蹤產(chǎn)品時(shí)需要做很大的改動(dòng)。為了解決這類問(wèn)題,于是誕生了OpenTracing規(guī)范,旨在統(tǒng)一鏈路追蹤系統(tǒng)的API。

二、OpenTracing規(guī)范

? OpenTracing 是一套分布式追蹤協(xié)議,與平臺(tái)和語(yǔ)言無(wú)關(guān),具有統(tǒng)一的接口規(guī)范,方便接入不同的分布式追蹤系統(tǒng)。

? OpenTracing語(yǔ)義規(guī)范詳見(jiàn):https://github.com/opentracing/specification/blob/master/specification.md

2.1 數(shù)據(jù)模型(Data Model)

? OpenTracing語(yǔ)義規(guī)范中定義的數(shù)據(jù)模型有 Trace、Sapn以及Reference。

2.1.1 Trace

? Trace表示一條完整的追蹤鏈路,例如:一個(gè)事務(wù)或者一個(gè)流程的執(zhí)行過(guò)程。一個(gè) Trace 是由一個(gè)或者多個(gè) Span 組成的有向無(wú)環(huán)圖(DAG)。

下圖表示一個(gè)由8個(gè)Span組成的Trace:

[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í)間軸方式更為直觀地展現(xiàn)該Trace:

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time[Span A···················································][Span B··············································][Span D··········································][Span C········································][Span E·······] [Span F··] [Span G··] [Span H··]

2.1.2 Span

? Span表示一個(gè)獨(dú)立的工作單元,它是一條追蹤鏈路的基本組成要素。例如:一次RPC調(diào)用、一次函數(shù)調(diào)用或者一次Http請(qǐng)求。

每個(gè)Span封裝了如下?tīng)顟B(tài):

  • 操作名稱用于表示該Span的任務(wù)名稱。 例如:一個(gè) RPC方法名, 一個(gè)函數(shù)名,或者大型任務(wù)中的子任務(wù)名稱。
  • 開(kāi)始時(shí)間戳任務(wù)開(kāi)始時(shí)間。
  • 結(jié)束時(shí)間戳。任務(wù)結(jié)束時(shí)間。通過(guò)Span的結(jié)束時(shí)間戳和開(kāi)始時(shí)間戳,就能夠計(jì)算出該Span的整體耗時(shí)。
  • 一組Span標(biāo)簽每一個(gè)Span標(biāo)簽是一個(gè)鍵值對(duì)。鍵必須是字符串,值可以是字符串、布爾或數(shù)值類型。
常見(jiàn)標(biāo)簽鍵可參考:https://github.com/opentracing/specification/blob/master/semantic_conventions.md

一組Span日志每一條Span日志由一個(gè)鍵值對(duì)和一個(gè)相應(yīng)的時(shí)間戳組成。鍵必須是字符串,值可以是任何類型。

常見(jiàn)日志鍵參考:https://github.com/opentracing/specification/blob/master/semantic_conventions.md

2.1.3 Reference

? 一個(gè)Span可以與一個(gè)或者多個(gè)Span存在因果關(guān)系,這種關(guān)系稱為Reference。OpenTracing目前定義了兩種關(guān)系:ChildOf(父子)關(guān)系 和 FollowsFrom(跟隨)關(guān)系。

  • ChildOf關(guān)系父Span的執(zhí)行依賴子Span的執(zhí)行結(jié)果,此時(shí)子Span對(duì)父Span的Reference關(guān)系是ChildOf。比如對(duì)于一次RPC調(diào)用,服務(wù)端的Span(子Span)與客戶端調(diào)用的Span(父Span)就是ChildOf關(guān)系。
  • FollowsFrom關(guān)系父Span的執(zhí)行不依賴子Span的執(zhí)行結(jié)果,此時(shí)子Span對(duì)父Span的Reference關(guān)系是FollowFrom。FollowFrom常用于表示異步調(diào)用,例如消息隊(duì)列中Consumer Span與Producer Span之間的關(guān)系。

2.2 應(yīng)用接口(API)

2.2.1 Tracer

? Tracer接口用于創(chuàng)建Span、跨進(jìn)程注入數(shù)據(jù)和提取數(shù)據(jù)。通常具有以下功能:

  • Start a new span
    創(chuàng)建并啟動(dòng)一個(gè)新的Span。
  • Inject
    將SpanContext注入載體(Carrier)。
  • Extract
    從載體(Carrier)中提取SpanContext。

2.2.2 Span

  • Retrieve a SpanContext
    返回Span對(duì)應(yīng)的SpanContext。
  • Overwrite the operation name
    更新操作名稱。
  • Set a span tag
    設(shè)置Span標(biāo)簽數(shù)據(jù)。
  • Log structured data
    記錄結(jié)構(gòu)化數(shù)據(jù)。
  • Set a baggage item
    baggage item是字符串型的鍵值對(duì),它對(duì)應(yīng)于某個(gè) Span,隨Trace一起傳播。由于每個(gè)鍵值都會(huì)被拷貝到每一個(gè)本地及遠(yuǎn)程的子Span,這可能導(dǎo)致巨大的網(wǎng)絡(luò)和CPU開(kāi)銷。
  • Get a baggage item
    獲取baggage item的值。
  • Finish
    結(jié)束一個(gè)Span。

2.2.3 Span Context

? 用于攜帶跨越服務(wù)邊界的數(shù)據(jù),包括trace ID、Span ID以及需要傳播到下游Span的baggage數(shù)據(jù)。在OpenTracing中,強(qiáng)制要求SpanContext實(shí)例不可變,以避免在Span完成和引用時(shí)出現(xiàn)復(fù)雜的生命周期問(wèn)題。

2.2.4 NoopTracer

? 所有對(duì)OpenTracing API的實(shí)現(xiàn),必須提供某種形式的NoopTracer,用于標(biāo)記控制OpenTracing或注入對(duì)測(cè)試無(wú)害的東西。

三、Jaeger

? Jaeger是Uber開(kāi)源的分布式追蹤系統(tǒng),它的應(yīng)用接口完全遵循OpenTracing規(guī)范。jaeger本身采用go語(yǔ)言編寫,具有跨平臺(tái)跨語(yǔ)言的特性,提供了各種語(yǔ)言的客戶端調(diào)用接口,例如c++、java、go、python、ruby、php、nodejs等。

項(xiàng)目地址:https://github.com/jaegertracing

3.1 Jaeger組件

  • jaeger-clientjaeger的客戶端代碼庫(kù),它實(shí)現(xiàn)了OpenTracing協(xié)議。當(dāng)我們的應(yīng)用程序?qū)⑵溲b配后,負(fù)責(zé)收集數(shù)據(jù),并發(fā)送到j(luò)aeger-agent。這是我們唯一需要編寫代碼的地方。
  • jaeger-agent負(fù)責(zé)接收從jaeger-client發(fā)來(lái)的Trace/Span信息,并批量上傳到j(luò)aeger-collector。
  • jaeger-collector負(fù)責(zé)接收從jaeger-agent發(fā)來(lái)的Trace/Span信息,并經(jīng)過(guò)校驗(yàn)、索引等處理,然后寫入到后端存儲(chǔ)。
  • data store負(fù)責(zé)數(shù)據(jù)存儲(chǔ)。Jaeger的數(shù)據(jù)存儲(chǔ)是一個(gè)可插拔的組件,目前支持Cassandra、ElasticSearch和Kafka。
  • jaeger-query & ui負(fù)責(zé)數(shù)據(jù)查詢,并通過(guò)前端界面展示查詢結(jié)果。

3.2 快速入門

? Jaeger官方提供了all-in-one鏡像,方便快速進(jìn)行測(cè)試:

# 拉取鏡像 $docker pull jaegertracing/all-in-one:latest# 運(yùn)行鏡像 $docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 14268:14268 -p 9411:9411 -p 16686:16686 jaegertracing/all-in-one:latest

? 通過(guò)all-in-one鏡像啟動(dòng),我們發(fā)現(xiàn)Jaeger占據(jù)了很多端口。以下是端口使用說(shuō)明:

? 啟動(dòng)后,我們可以訪問(wèn) http://localhost:16686 ,在瀏覽器中查看和查詢收集的數(shù)據(jù)。

? 由于通過(guò)all-in-one鏡像方式收集的數(shù)據(jù)都存儲(chǔ)在docker中,無(wú)法持久保存,所以只能用于開(kāi)發(fā)或者測(cè)試環(huán)境,無(wú)法用于生產(chǎn)環(huán)境。生產(chǎn)環(huán)境中需要依據(jù)實(shí)際情況,分別部署各個(gè)組件。

四、Jaeger在業(yè)務(wù)代碼中的應(yīng)用

? 系統(tǒng)中使用Jaeger非常簡(jiǎn)單,只需要在原有程序中插入少量代碼。以下代碼模擬了一個(gè)查詢用戶賬戶余額,執(zhí)行扣款的業(yè)務(wù)場(chǎng)景:

4.1 初始化jaeger函數(shù)

? 主要是按照實(shí)際需要配置有關(guān)參數(shù),例如服務(wù)名稱、采樣模式、采樣比例等等。

func initJaeger() (tracer opentracing.Tracer, closer io.Closer, err error) {// 構(gòu)造配置信息cfg := &config.Configuration{// 設(shè)置服務(wù)名稱ServiceName: "ServiceAmount",// 設(shè)置采樣參數(shù)Sampler: &config.SamplerConfig{Type: "const", // 全采樣模式Param: 1, // 開(kāi)啟狀態(tài)},}// 生成一條新tracertracer, closer, err = cfg.NewTracer()if err == nil {// 設(shè)置tracer為全局單例對(duì)象opentracing.SetGlobalTracer(tracer)}return }

4.2 檢測(cè)用戶余額函數(shù)

? 用于檢測(cè)用戶余額,模擬一個(gè)子任務(wù)Span。

func CheckBalance(request string, ctx context.Context) {// 創(chuàng)建子spanspan, _ := opentracing.StartSpanFromContext(ctx, "CheckBalance")// 模擬系統(tǒng)進(jìn)行一系列的操作,耗時(shí)1/3秒time.Sleep(time.Second / 3)// 示例:將需要追蹤的信息放入tagspan.SetTag("request", request)span.SetTag("reply", "CheckBalance reply")// 結(jié)束當(dāng)前spanspan.Finish()log.Println("CheckBalance is done") }

4.3 從用戶賬戶扣款函數(shù)

? 從用戶賬戶扣款,模擬一個(gè)子任務(wù)span。

func Reduction(request string, ctx context.Context) {// 創(chuàng)建子spanspan, _ := opentracing.StartSpanFromContext(ctx, "Reduction")// 模擬系統(tǒng)進(jìn)行一系列的操作,耗時(shí)1/2秒time.Sleep(time.Second / 2)// 示例:將需要追蹤的信息放入tagspan.SetTag("request", request)span.SetTag("reply", "Reduction reply")// 結(jié)束當(dāng)前spanspan.Finish()log.Println("Reduction is done") }

4.4 主函數(shù)

? 初始化jaeger環(huán)境,生成tracer,創(chuàng)建父span,以及調(diào)用查詢余額和扣款兩個(gè)子任務(wù)span。

package mainimport ("context""fmt""github.com/opentracing/opentracing-go""github.com/uber/jaeger-client-go/config""io""log""time" )func main() {// 初始化jaeger,創(chuàng)建一條新tracertracer, closer, err := initJaeger()if err != nil {panic(fmt.Sprintf("ERROR: cannot init Jaeger: %vn", err))}defer closer.Close()// 創(chuàng)建一個(gè)新span,作為父span,開(kāi)始計(jì)費(fèi)過(guò)程span := tracer.StartSpan("CalculateFee")// 生成父span的contextctx := opentracing.ContextWithSpan(context.Background(), span)// 示例:設(shè)置一個(gè)span標(biāo)簽信息span.SetTag("db.instance", "customers")// 示例:輸出一條span日志信息span.LogKV("event", "timed out")// 將父span的context作為參數(shù),調(diào)用檢測(cè)用戶余額函數(shù)CheckBalance("CheckBalance request", ctx)// 將父span的context作為參數(shù),調(diào)用扣款函數(shù)Reduction("Reduction request", ctx)// 結(jié)束父spanspan.Finish() }

五、Jaeger在gRPC微服務(wù)中的應(yīng)用

? 我們依然模擬了一個(gè)查詢用戶賬戶余額,執(zhí)行扣款的業(yè)務(wù)場(chǎng)景,并把查詢用戶賬戶余額和執(zhí)行扣款功能改造為gRPC微服務(wù):

5.1 gRPC Server端代碼

main.go:

? 代碼使用了第三方依賴庫(kù)http://github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing,該依賴庫(kù)將OpenTracing封裝為通用的gRPC中間件,并通過(guò)gRPC攔截器無(wú)縫嵌入gRPC服務(wù)中。

package mainimport ("fmt""github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing""github.com/opentracing/opentracing-go""github.com/uber/jaeger-client-go/config""google.golang.org/grpc""google.golang.org/grpc/reflection""grpc-jaeger-server/account""io""log""net" )// 初始化jaeger func initJaeger() (tracer opentracing.Tracer, closer io.Closer, err error) {// 構(gòu)造配置信息cfg := &config.Configuration{// 設(shè)置服務(wù)名稱ServiceName: "ServiceAmount",// 設(shè)置采樣參數(shù)Sampler: &config.SamplerConfig{Type: "const", // 全采樣模式Param: 1, // 開(kāi)啟全采樣模式},}// 生成一條新tracertracer, closer, err = cfg.NewTracer()if err == nil {// 設(shè)置tracer為全局單例對(duì)象opentracing.SetGlobalTracer(tracer)}return }func main() {// 初始化jaeger,創(chuàng)建一條新tracertracer, closer, err := initJaeger()if err != nil {panic(fmt.Sprintf("ERROR: cannot init Jaeger: %vn", err))}defer closer.Close()log.Println("succeed to init jaeger")// 注冊(cè)gRPC account服務(wù)server := grpc.NewServer(grpc.UnaryInterceptor(grpc_opentracing.UnaryServerInterceptor(grpc_opentracing.WithTracer(tracer))))account.RegisterAccountServer(server, &AccountServer{})reflection.Register(server)log.Println("succeed to register account service")// 監(jiān)聽(tīng)gRPC account服務(wù)端口listener, err := net.Listen("tcp", ":8080")if err != nil {log.Println(err)return}log.Println("starting register account service")// 開(kāi)啟gRpc account服務(wù)if err := server.Serve(listener); err != nil {log.Println(err)return} }

計(jì)費(fèi)微服務(wù) accountsever.go:

package mainimport ("github.com/opentracing/opentracing-go""golang.org/x/net/context""grpc-jaeger-server/account""time" )// 計(jì)費(fèi)服務(wù) type AccountServer struct{}// 檢測(cè)用戶余額微服務(wù),模擬子span任務(wù) func (s *AccountServer) CheckBalance(ctx context.Context, request *account.CheckBalanceRequest) (response *account.CheckBalanceResponse, err error) {response = &account.CheckBalanceResponse{Reply: "CheckBalance Reply", // 處理結(jié)果}// 創(chuàng)建子spanspan, _ := opentracing.StartSpanFromContext(ctx, "CheckBalance")// 模擬系統(tǒng)進(jìn)行一系列的操作,耗時(shí)1/3秒time.Sleep(time.Second / 3)// 將需要追蹤的信息放入tagspan.SetTag("request", request)span.SetTag("reply", response)// 結(jié)束當(dāng)前spanspan.Finish()return response, err }// 從用戶賬戶扣款微服務(wù),模擬子span任務(wù) func (s *AccountServer) Reduction(ctx context.Context, request *account.ReductionRequest) (response *account.ReductionResponse, err error) {response = &account.ReductionResponse{Reply: "Reduction Reply", // 處理結(jié)果}// 創(chuàng)建子spanspan, _ := opentracing.StartSpanFromContext(ctx, "Reduction")// 模擬系統(tǒng)進(jìn)行一系列的操作,耗時(shí)1/3秒time.Sleep(time.Second / 3)// 將需要追蹤的信息放入tagspan.SetTag("request", request)span.SetTag("reply", response)// 結(jié)束當(dāng)前spanspan.Finish()return response, err }

5.2 gRPC Client端代碼main.go:

package mainimport ("context""fmt""github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing""github.com/opentracing/opentracing-go""github.com/uber/jaeger-client-go/config""google.golang.org/grpc""grpc-jaeger-client/account""io""log" )// 初始化jaeger func initJaeger() (tracer opentracing.Tracer, closer io.Closer, err error) {// 構(gòu)造配置信息cfg := &config.Configuration{// 設(shè)置服務(wù)名稱ServiceName: "ServiceAmount",// 設(shè)置采樣參數(shù)Sampler: &config.SamplerConfig{Type: "const", // 全采樣模式Param: 1, // 開(kāi)啟全采樣模式},}// 生成一條新tracertracer, closer, err = cfg.NewTracer()if err == nil {// 設(shè)置tracer為全局單例對(duì)象opentracing.SetGlobalTracer(tracer)}return }func main() {// 初始化jaeger,創(chuàng)建一條新tracertracer, closer, err := initJaeger()if err != nil {panic(fmt.Sprintf("ERROR: cannot init Jaeger: %vn", err))}defer closer.Close()log.Println("succeed to init jaeger")// 創(chuàng)建一個(gè)新span,作為父spanspan := tracer.StartSpan("CalculateFee")// 函數(shù)返回時(shí)關(guān)閉spandefer span.Finish()// 生成span的contextctx := opentracing.ContextWithSpan(context.Background(), span)// 連接gRPC serverconn, err := grpc.Dial("localhost:8080",grpc.WithInsecure(),grpc.WithUnaryInterceptor(grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(tracer),)))if err != nil {log.Println(err)return}// 創(chuàng)建gRPC計(jì)費(fèi)服務(wù)客戶端client := account.NewAccountClient(conn)// 將父span的context作為參數(shù),調(diào)用檢測(cè)用戶余額的gRPC微服務(wù)checkBalanceResponse, err := client.CheckBalance(ctx,&account.CheckBalanceRequest{Account: "user account",})if err != nil {log.Println(err)return}log.Println(checkBalanceResponse)// 將父span的context作為參數(shù),調(diào)用扣款的gRPC微服務(wù)reductionResponse, err := client.Reduction(ctx,&account.ReductionRequest{Account: "user account",Amount: 1,})if err != nil {log.Println(err)return}log.Println(reductionResponse) }注:
本文全部源代碼位于:https://github.com/wangshizebin/micro-service
本文時(shí)候用的開(kāi)發(fā)工具為:goland
原文鏈接:https://www.cnblogs.com/wanghao72214/p/13932810.html

如果覺(jué)得本文對(duì)你有幫助,可以點(diǎn)贊關(guān)注支持一下,也可以點(diǎn)進(jìn)我主頁(yè)關(guān)注我公眾號(hào),上面有更多技術(shù)干貨文章以及相關(guān)資料共享,大家一起學(xué)習(xí)進(jìn)步!

總結(jié)

以上是生活随笔為你收集整理的ajax请求是宏任务还是微任务_微服务-如何解决链路追踪问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。