色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于go-zero如何追蹤的原理追溯

OSC開源社區 ? 來源:OSC開源社區 ? 2022-12-22 10:35 ? 次閱讀

前言

鏈路追蹤是每個微服務架構下必備的利器,go-zero 當然早已經為我們考慮好了,只需要在配置中添加配置即可使用。

關于 go-zero 如何追蹤的原理追溯,之前已經有同學分享,這里我就不再多說,如果有想了解的同學去 https://mp.weixin.qq.com/s/hJEWcWc3PnGfWfbPCHfM9g 這個鏈接看就好了。默認會在 api 的中間件與 rpc 的 interceptor 添加追蹤,如果有不了解 go-zero 默認如何使用默認的鏈路追蹤的,請移步我的開源項目 go-zero-looklook 文檔 https://github.com/Mikaelemmmm/go-zero-looklook/blob/main/doc/chinese/12-%E9%93%BE%E8%B7%AF%E8%BF%BD%E8%B8%AA.md。

今天我想講的是,除了 go-zero 默認在 api 的 middleware 與 rpc 的 interceptor 中幫我們集成好的鏈路追蹤,我們想自己在某些本地方法添加鏈路追蹤代碼或者我們想在 api 發送一個消息給 mq 服務時候想把整個鏈路包含 mq 的 producer、consumer 穿起來,在 go-zero 中該如何做。

場景

我們先簡單講一下我們的小 demo 的場景,一個請求進來調用 api 的 Login 方法,在 Login 方法中先調用 rpc 的 GetUserByMobile 方法,之后在調用 api 本地的 local 方法,緊接著調用 rabbitmq 傳遞消息到 mq 服務。

go-zero 默認集成了 jaeger、zinpink,這里我們就以 jaeger 為例

我們希望看到的鏈路是

4ae48258-813f-11ed-8abf-dac502259ad0.pngapi.Login -> rpc.GetUserByMobile

也就是 api 衍生出來三條子鏈路,api.producerMq 有一條調用 mq.Consumer 的子鏈路。

我們想要將一個方法添加到鏈路中需要兩個因素,一個 traceId,一個span,當我們在同一個 traceId 下開啟 span 把相關的 span 都串聯起來,如果想形成父子關系,就要把 span 之間相互串聯起來,因為「微服務實踐」公眾號中講解原理太多,我這里就簡單提一下不涉及過多,如果不是特別熟悉原理可以看文章開頭推薦的文章,這里我們只需要知道 traceIdspanId 關系就好。

核心業務代碼

1、首先 API 中 LoginLogic 代碼

typeLoginLogicstruct{
logx.Logger
ctxcontext.Context
svcCtx*svc.ServiceContext
}

funcNewLoginLogic(ctxcontext.Context,svcCtx*svc.ServiceContext)*LoginLogic{
return&LoginLogic{
Logger:logx.WithContext(ctx),
ctx:ctx,
svcCtx:svcCtx,
}
}

typeMsgBodystruct{
Carrier*propagation.HeaderCarrier
Msgstring
}

func(l*LoginLogic)Login(req*types.RegisterReq)(*types.AccessTokenResp,error){
resp,err:=l.svcCtx.UserRpc.GetUserByMobile(l.ctx,&usercenter.GetUserByMobileReq{
Mobile:req.Mobile,
})
iferr!=nil{
return&types.AccessTokenResp{},nil
}

l.local()

tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
spanCtx,span :=tracer.Start(l.ctx,"send_msg_mq",oteltrace.WithSpanKind(oteltrace.SpanKindProducer))
carrier:=&propagation.HeaderCarrier{}
otel.GetTextMapPropagator().Inject(spanCtx,carrier)

producer:=rabbit.NewRabbitmqPublisher(RabbitmqDNS)
msg:=&MsgBody{
Carrier:carrier,
Msg:req.Mobile,
}
b,err:=json.Marshal(msg)
iferr!=nil{
panic(err)
}

iferr:=producer.Publish(spanCtx,ExchangeName,RoutineKeys,b);err!=nil{
logx.Errorf("PublishFail,msg:%s,err:%v",msg,err)
}
span.End()

return&types.AccessTokenResp{
AccessExpire:resp.User.Id,
},err
}

func(l*LoginLogic)local(){
tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
_,span :=tracer.Start(l.ctx,"local",oteltrace.WithSpanKind(oteltrace.SpanKindInternal))
deferspan.End()

//執行你的代碼.....
}

2、rpc 中 GetUserByMobile 的代碼

func(s*Logic)GetUserByMobile(context.Context,*usercenterPb.GetUserByMobileReq)(*usercenterPb.GetUserByMobileResp,error){
vo:=&usercenterPb.UserVo{
Id:1,
}
return&usercenterPb.GetUserByMobileResp{
User:vo,
},nil
}

3、mq 中 Consumer 的代碼

typeMsgBodystruct{
Carrier*propagation.HeaderCarrier
Msgstring
}

func(c*consumer)Consumer(ctxcontext.Context,data[]byte)error{
varmsgMsgBody
iferr:=json.Unmarshal(data,&msg);err!=nil{
logx.Errorf("consumererr:%v",err)
}else{
logx.Infof("consumerOneConsumer,msg:%+v",msg)

wireContext:=otel.GetTextMapPropagator().Extract(ctx,msg.Carrier)
tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
_,span :=tracer.Start(wireContext,"mq_consumer_msg",oteltrace.WithSpanKind(oteltrace.SpanKindConsumer))

deferspan.End()
}

returnnil
}

代碼詳解

1、go-zero 默認集成

當一個請求進入 api 后,我們可以在 go-zero 源碼中查看到 https://github.com/zeromicro/go-zero/blob/master/rest/engine.go#L92。go-zero 已經在 api 的 middleware 中幫我們添加了第一層 trace,當進入 Login 方法內,我們調用了 rpc 的 GetUserByMobile 方法,通過 go-zero 的源碼 https://github.com/zeromicro/go-zero/blob/master/zrpc/internal/rpcserver.go#L55 可以看到在 rpc 的 interceptor 也默認幫我們添加好了,這兩層都是 go-zero 默認幫我們做好的。

2、本地方法

當調用完 rpc 的 GetUserByMobile 之后,api 調用了本地的 local,如果我們想在整個鏈路上體現出來調用了本地 local 方法,那默認的 go-zero 是沒有幫我們做的,需要我們手動來添加。

tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
_,span :=tracer.Start(l.ctx,"local",oteltrace.WithSpanKind(oteltrace.SpanKindInternal))
deferspan.End()

//執行你的代碼.....

我們通過上面代碼拿到 tracer,ctx 之后開啟一個 local 的 span,因為 start 時候會從 ctx 獲取父 span 所以會將 local 方法與 Login 串聯起父子調用關系,這樣就將本次操作加入了這個鏈路

3、mq 的 producer 到 mq 的 consumer

我們在mq傳遞中如何串聯起來這個鏈路呢?也就是形成 api.Login->api.producer->mq.Consumer

想一下原理,雖然跨越了網絡,api 可以通過 header 傳遞,rpc 可以通過 metadata 傳遞,那么 mq 是不是也可以通過 headerbody 傳遞就可以了,按照這個想法來看下我門的代碼。

tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
spanCtx,span :=tracer.Start(l.ctx,"send_msg_mq",oteltrace.WithSpanKind(oteltrace.SpanKindProducer))
carrier:=&propagation.HeaderCarrier{}
otel.GetTextMapPropagator().Inject(spanCtx,carrier)

producer:=rabbit.NewRabbitmqPublisher(RabbitmqDNS)
msg:=&MsgBody{
Carrier:carrier,
Msg:req.Mobile,
}
b,err:=json.Marshal(msg)
iferr!=nil{
panic(err)
}

iferr:=producer.Publish(spanCtx,ExchangeName,RoutineKeys,b);err!=nil{
logx.Errorf("PublishFail,msg:%s,err:%v",msg,err)
}
span.End()

首先獲取到了這個全局的 tracer,然后開啟一個 producerspan,跟 local 方法一樣,我們開啟 producerspan 時候也是通過 ctx 獲取到上一級父級 span,這樣就可以將 producerspanLogin 形成父子 span 調用關系,那我們想將 producerspan 與 mq 的 consumer 中的 span 形成調用父子關系怎么做?我們將 api.producerspanCtx 注入到 carrier 中,這里我們通過 mq 的 bodycarrier 發送給 consumer,發送完成我們 stop 我們的 producer,那么 producer 的這層鏈路完成了。

隨后我們來看 mq-consumer 在接收到 body 消息之后怎么做的。

typeMsgBodystruct{
Carrier*propagation.HeaderCarrier
Msgstring
}

func(c*consumer)Consumer(ctxcontext.Context,data[]byte)error{
varmsgMsgBody
iferr:=json.Unmarshal(data,&msg);err!=nil{
logx.Errorf("consumererr:%v",err)
}else{
logx.Infof("consumerOneConsumer,msg:%+v",msg)

wireContext:=otel.GetTextMapPropagator().Extract(ctx,msg.Carrier)
tracer:=otel.GetTracerProvider().Tracer(trace.TraceName)
_,span :=tracer.Start(wireContext,"mq_consumer_msg",oteltrace.WithSpanKind(oteltrace.SpanKindConsumer))

deferspan.End()
}

returnnil
}

consumer 接收到消息后反序列化出來 Carrier *propagation.HeaderCarrier,然后通過 otel.GetTextMapPropagator().Extract 取出來 api.producer 注入的 wireContext,在通過 tracer.Start、wireContext 創建 consumerspan,這樣 consumer 就是 api.producer 的子 span,就形成了調用鏈路關系,最終我們得到的關系就是

4ae48258-813f-11ed-8abf-dac502259ad0.pngapi.Login -> rpc.GetUserByMobile

讓我們來調用一下 Logic 方法,看下 jaeger 中的鏈路如果與我們預想的鏈路一致,so happy~

4b64a802-813f-11ed-8abf-dac502259ad0.jpg

項目地址

go-zero 微服務框架:https://github.com/zeromicro/go-zero

go-zero 微服務最佳實踐項目:https://github.com/Mikaelemmmm/go-zero-looklook

歡迎使用 go-zerostar 支持我們!

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Go
    Go
    +關注

    關注

    0

    文章

    43

    瀏覽量

    12268
  • 微服務
    +關注

    關注

    0

    文章

    142

    瀏覽量

    7399

原文標題:玩轉 Go 鏈路追蹤

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    適合于藥品追溯智能一體機的工控主板

    在醫藥行業中,藥品的管理與追溯尤為重要。隨著技術的不斷進步,藥品追溯智能一體機應運而生,成為藥品高效管理的得力助手。藥品追溯智能一體機?是一種集成化的設備,主要用于生成、管理和查詢藥品的追溯
    的頭像 發表于 01-23 10:10 ?63次閱讀
    適合于藥品<b class='flag-5'>追溯</b>智能一體機的工控主板

    RFID電子標簽在石油鉆桿追溯管理中的應用

    上海岳冉RFID技術在石油鉆桿追溯管理中的應用,研發針對金屬工具高溫工作環境的RFID耐高溫標簽。該標簽能夠埋入鉆桿接頭孔中,實現對每根鉆桿的精確追蹤和管理。
    的頭像 發表于 01-13 16:18 ?89次閱讀

    智譜推出深度推理模型GLM-Zero預覽版

    近日,智譜公司正式發布了其深度推理模型GLM-Zero的預覽版——GLM-Zero-Preview。這款模型標志著智譜在擴展強化學習技術訓練推理模型方面的重大突破,成為其首個專注于增強AI推理能力
    的頭像 發表于 01-03 10:42 ?164次閱讀

    智譜GLM-Zero深度推理模型預覽版正式上線

    近日,智譜公司宣布其深度推理模型GLM-Zero的初代版本——GLM-Zero-Preview已正式上線。這款模型是智譜首個基于擴展強化學習技術訓練的推理模型,標志著智譜在AI推理領域邁出了重要一步
    的頭像 發表于 01-02 10:55 ?157次閱讀

    在學習go語言的過程踩過的坑

    作為一個5年的phper,這兩年公司和個人都在順應技術趨勢,新項目慢慢從php轉向了go語言,從2021年到現在,筆者手上也先后開發了兩個go項目。在學習go語言的過程中也學習并總結了一些相關的東西,這篇文章就分享下自己踩過的一
    的頭像 發表于 11-11 09:22 ?196次閱讀

    go語言如何解決并發問題

    作為一個后端開發,日常工作中接觸最多的兩門語言就是PHP和GO了。無可否認,PHP確實是最好的語言(手動狗頭哈哈),寫起來真的很舒爽,沒有任何心智負擔,字符串和整型壓根就不用區分,開發速度真的是比
    的頭像 發表于 10-23 13:38 ?168次閱讀
    <b class='flag-5'>go</b>語言如何解決并發問題

    如何遠離網絡追蹤

    ?隨著科技不斷發展,生活、工作等都離不開網絡。但網絡追蹤技術也隨著科技的進步不斷發展,人們在網絡上的在線活動越來越容易被追蹤和監控。這會威脅到個人隱私、信息泄露、身份盜竊等嚴重后果。所以,今天我想
    的頭像 發表于 09-03 16:57 ?523次閱讀
    如何遠離網絡<b class='flag-5'>追蹤</b>

    三十分鐘入門基礎Go Java小子版

    前言 Go語言定義 Go(又稱 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 開發的一種靜態、強類型、編譯型語言。Go 語言
    的頭像 發表于 08-12 14:32 ?775次閱讀
    三十分鐘入門基礎<b class='flag-5'>Go</b> Java小子版

    動態追溯方法:徹底革新軟件測試

    動態追溯方法為解決軟件開發中追溯的挑戰提供了創新的解決方案。通過自動和動態地鏈接需求和測試用例,使測試過程顯著提高效率和精確度。該方法減少了手工操作,改善了故障分析,并確保了持續的追溯性,最終提升了軟件的質量和可靠性。采用動態
    的頭像 發表于 07-05 17:40 ?452次閱讀
    動態<b class='flag-5'>追溯</b>方法:徹底革新軟件測試

    求助,關于PSoC4000S POWER_DRILL2GO下降壓擺率的疑問求解

    我不確定來自哪個版本,但數據表中列出了 PSoC4000S POWER_DRILL2GO下降壓擺率。(1V/ms 最小,最大 67V/ms) 目前的設計并不能滿足這個要求
    發表于 05-21 08:14

    請問STVP+COSMIC環境下的go to definition怎么用?

    STVP+COSMIC環境下的go to definition怎么用? 我現在go to definition在一個宏定義的時候有效果,但是函數什么的沒用,是怎么回事呢,是不是工程里面沒有設置好,求大家幫幫忙?
    發表于 05-11 06:11

    關于go中接口類型的表示方法

    go是一個靜態性語言,每個變量都有靜態的類型,因此每個變量在編譯階段中有明確的變量類型,比如像:int、float32、MyType。
    的頭像 發表于 04-28 10:13 ?402次閱讀

    MES系統對生產追溯的好處

    。 2. 提高生產效率:MES系統能夠對生產過程進行優化和調度,確保生產線的平衡和高效運轉,減少生產停機時間和資源浪費,提高生產效率。 3. 提供可追溯性:MES系統可以記錄和追蹤產品的生產過程,包括原材料的來源、加工過程中的各項參數、人員
    的頭像 發表于 04-08 10:30 ?601次閱讀
    MES系統對生產<b class='flag-5'>追溯</b>的好處

    在CYUSB3304-68LTXC上電時將RESETN輸入切換為L/H,可以聯動控制POWER_DRILL2GO端子嗎?

    我有一個關于 HX3 的問題。 如果在 CYUSB3304-68LTXC 上電時將 RESETN 輸入切換為 L/H,是否可以聯動控制POWER_DRILL2GO端子? 例如,當RESETN輸入為L時, POWER_DRILL2GO
    發表于 03-06 07:45

    PMG1 PoR復位時POWER_DRILL2GO什么時候進入?

    我有兩個關于 PMG1 PoR 的問題。 1.復位時POWER_DRILL2GO什么時候進入? 也許您想在電壓低于預設值時強制 EZ-PD? PMG1-S1 MCU 設備復位
    發表于 03-06 06:03
    主站蜘蛛池模板: 曰产无码久久久久久精品 | 动漫美女被爆挤奶歪歪漫画 | 2021国产精品一卡2卡三卡4卡 | 俄罗斯人与动ZOZ0 | 樱花草在线观看影院 | 台湾佬休闲中性娱乐网 | 成人中文在线 | 精子网久久国产精品 | 午夜福利免费视频921000电影 | 国语大学生自产拍在线观看 | 午夜伦午夜伦锂电影 | 永久精品视频无码一区 | 亚洲无线码一区在线观看 | 欧美人与禽ZOZO性伦交视频 | 虫族bl文全肉高h | 精品人妻伦一二三区久久AAA片 | 精品少妇爆AV无码专区 | 久久伊人精品青青草原2021 | 99精品视频在线观看免费播放 | 欧美性黑吊xxx | 在线精品国精品国产不卡 | 国产精品成久久久久三级四虎 | 欧美亚洲国产手机在线有码 | 性xxxx18公交车 | 北条麻妃久久99精品 | 动漫美女被爆挤奶歪歪漫画 | 欧美日韩北条麻妃一区二区 | 亚洲国产区中文在线观看 | 秋霞特色大片18岁入口 | 午夜福利免费0948视频 | 扒开老师大腿猛进AAA片 | 午夜一级毛片看看 | 少爷不要别揉了高H | 99热久久这里只有精品 | 37大但人文艺术A级都市天气 | 国产亚洲精品第一区香蕉 | 日韩免费精品视频 | 乱码午夜-极品国产内射 | 两个客户一起吃我的奶 | 久久成人无码国产免费播放 | 久久66热在线视频精品 |