一、背景介绍

由于在微服务架构中,服务之间的调用关系多而复杂,所以有必要对它们之间的调用链路进行追踪、分析,判断是哪里出了问题,或者哪里耗时过多。

最近接到了这个需求,添加全链路追踪,所以研究并实践了一下,还不太深刻,若有错误的地方欢迎指正。

二、OpenTracing相关概念介绍

首先,要实现全链路追踪,必须先理解OpenTracing的一些基本概念。OpenTracing为分布式链路追踪制定了一个统一的标准。只要是按照此标准实现的服务,就能够完整的进行分布式追踪。

1. Span

Span可以被翻译为跨度,可以理解为一次方法调用,一个程序块的调用,或者一次RPC/数据库访问。

Span之间是有关系的,child of 和 follow of。比如一次RPC的调用,RPC客户端和服务端的span就形成了父子关系。

2. Trace

Trace表示一个调用链,比如在分布式服务中,一个客户端的请求,在后台可能经过了层层的调用,那么每一次调用就相当于一个span,而这一整条调用链路,可以理解成一个trace。

Trace有一个全局唯一的ID。

三、Go2sky简介

Go2sky是Golang提供给开发者实现SkyWalking agent探针的包,可以通过它来实现向SkyWalking Collector上报数据。

快速入门:GitHub-Go2Sky

1. 创建Reporter、Tracer

SkyWalking支持http和gRpc两种方式收集数据,在Go2sky中,想要上报数据,先创建一个GRPCReporter.

Tracer代表了本程序中的一条调用链路。

本程序中的所有span都会与服务名为example的服务相关联。

2. 创建Span

Span有三种类型:LocalSpan、EntrySpan、ExitSpan。

LocalSpan:可以用来表示本程序内的一次调用。

EntrySpan:用来从下游服务提取context信息。

ExitSpan:  用来向上游服务注入context信息。

在创建span时,上下文参数传入context.Backround() ,就表示它是root span。

3. 创建sub span

在创建LocalSpan和EntrySpan的时候,返回值会返回一个context信息(ctx),通过它来创建sub span,来与root span形成父子关系。

4. End Span

必须要确保结束span,它们才可以被上传给skywalking。

5. 关联Span

我们在程序中创建的span,是怎么关联起来形成一个调用链的呢。

在同一个程序中,向上面那样,创建root span 和 sub span即可。

在不同的程序中,下游服务使用ExitSpan向上游注入context信息,上游服务使用EntrySpan从下游提取context信息。Entry和Exit使得skywalking可以分析,从而生成拓扑图和度量指标。

四、实战 -- 跨程序追踪RPC调用

看到这里,有了基本的概念,以及Go2sky的基本用法,但是仍然不能够对RPC进行有效的追踪。

因为上图中的例子使用的是http请求,它本身就封装了Get和Set方法,可以很轻松的注入和提取context信息。但是RPC请求并没有,想要追踪别的类型跨程序的调用也没有。

所以我们要自己将context信息在进行调用的时候,从下游服务传给上游服务,然后自己定义注入和提取的方法。

下面只贴出了链路追踪部分的代码,其它的比如rpc相关的部分代码省略了(不然又臭又长,还难看)。

1. Client端 (下游服务)

定义请求信息的结构体:

type Req struct {A       intHeader  string        // 添加此字段,用于传递context信息
}

定义context信息的注入方法:

func (p *Req) Set(key, value string) error {p.Header = fmt.Sprintf("%s:%s", key, value)return nil
}

创建reporter和tracer:

r, err = reporter.NewGRPCReporter("192.168.204.130:11800")
if err != nil {logs.Info("[New GRPC Reporter Error]: [%v]", err)return
}// 这个程序中所有的span都会跟服务名叫RTS_Test的服务关联起来
tracer, err = go2sky.NewTracer("RTS_Test", go2sky.WithReporter(r), go2sky.WithInstance("RTS_Test_1"))
if err != nil {logs.Info("[New Tracer Error]: [%v]", err)return
}
tracer.WaitUntilRegister()

rpc调用以及创建span:

在创建ExitSpan的时候,传入了一个函数,函数实现就是我们定义的如何注入context信息的函数。

它会在CreateExitSpan()函数的内部被调用,header的值不需要我们管,它在CreateExitSpan函数内部生成的。我们只需要负责在上游服务中把它提取出来即可。

我目前的理解是,只需要在下游服务中负责把这个header按一定规则拼接,传给上游服务,然后在上游服务中按照规则将header解析出来,skywalking通过分析,即可将上下游的span关联起来。

func OnSnapshot() {// client := GetClinet()// 表示收到客户端请求,因为只追踪后台服务之间的链路,所以这里不需要提取context信息span2, ctx, err := tracer.CreateEntrySpan(context.Background(), "/API/Snapshot", func() (string, error){return "", nil})if err != nil {logs.Info("[Create Exit Span Error]: [%v]", err)return}span2.SetComponent(5200)// 表示rpc调用的span,这里需要向上游服务注入context信息,即参数中的headerreq := Req{3, ""}span1, err := tracer.CreateExitSpan(ctx, "/Service/OnSnapshot", "RTS_Server", func(header string) error{return req.Set(propagation.Header, header)})if err != nil {logs.Info("[Create Exit Span Error]: [%v]", err)return}span1.SetComponent(5200)    // Golang程序使用范围是[5000, 6000),还要在skywalking中配置,config目录下的component-libraries.yml文件var res Res// rpc调用err = conn.Call("Req.Snapshot", req, &res)if err != nil {logs.Info("[RPC Call Snapshot Error]: [%v]", err)return} else {logs.Info("[RPC Call Snapshot Success]: [%s]", res)}span1.End()span2.End()    // 一定要确保span被结束// s1 := ReportedSpan(span1)// s2 := ReportedSpan(span2)// spans := []go2sky.ReportedSpan{s1, s2}// r.Send(spans)
}

2. Server端 (上游服务)

定义请求信息的结构体:

type ReqBody struct {A       intHeader  string
}

定义context信息的提取方法:

func (p *ReqBody) Get(key string) string {subs := strings.Split(p.Header, ":")if len(subs) != 2 || subs[0] != key {return ""}return subs[1]
}

创建reporter和tracer:

r, err = reporter.NewGRPCReporter("192.168.204.130:11800")
if err != nil {logs.Info("[New GRPC Reporter Error]: [%v]\n", err)return
}tracer, err = go2sky.NewTracer("Service_Test", go2sky.WithReporter(r), go2sky.WithInstance("Service_Test_1"))
if err != nil {logs.Info("[New Tracer Error]: [%v]\n", err)return
}
tracer.WaitUntilRegister()

创建span:

在创建EntrySpan时,调用Get()方法提取context信息

func (p *Req)Snapshot(req ReqBody, res *Res) error {// 表示收到 rpc 客户端的请求,这里需要提取context信息span1, ctx, err := tracer.CreateEntrySpan(context.Background(), "/Service/OnSnapshot/QueringSnapshot", func() (string, error){return req.Get(propagation.Header), nil})if err != nil {logs.Info("[Create Exit Span Error]: [%v]\n", err)return err}span1.SetComponent(5200)// span1.SetPeer("Service_Test")// 表示去请求了一次数据库span2, err := tracer.CreateExitSpan(ctx, "/database/QuerySnapshot", "APIService", func(header string) error {return nil})span2.SetComponent(5200)time.Sleep(time.Millisecond * 6)*res = "Return Snapshot Info"span2.End()span1.End()// s1 := ReportedSpan(span1)// s2 := ReportedSpan(span2)// spans := []go2sky.ReportedSpan{s1, s2}// r.Send(spans)return nil
}

3. 结果展示

链路追踪:

拓扑图:

Go2sky -- Golang用skywalking实现全链路追踪相关推荐

  1. Springcloud 集成 Skywalking 实现全链路追踪

    下载链接 https://skywalking.apache.org/downloads/ 本地搭建springcloud工程,偷懒可参考gitee https://gitee.com/wangLi1 ...

  2. skywalking 安装_SkyWalking全链路追踪利器

    随着目前系统架构的复杂度越来越高(中台.微服务),并且线上应用的多级监控覆盖到了通讯.应用处理过程监控并且实现端到端的应用监测,线上性能故障的快速定位修复:而传统的监控分析方式已经无法满足我们的需求, ...

  3. skywalking与pinpoint全链路追踪方案对比

    由于公司目前有200多微服务,微服务之间的调用关系错综复杂,调用关系人工维护基本不可能实现,需要调研一套全链路追踪方案,初步调研之后选取了skywalking和pinpoint进行对比; 选取skyw ...

  4. Skywalking全链路追踪使用说明

    1.背景与需求: 随着业务规模的不断增大,系统的复杂度也越来越高,我们的软件架构也进入了分布式的阶段,服务按照不同的维度进行拆分,那么一次请求可能横跨多个服务模块.项目,依赖的中间件也越来越多,其中任 ...

  5. 使用Skywalking实现全链路监控

    https://opentalk.upyun.com/334.html 2017 年 10 月 29 日,又拍云 Open Talk 联合 Spring Cloud 中国社区成功举办了"进击 ...

  6. go 链路追踪_Golang在七牛全链路追踪中的实践

    1.Go在七⽜牛全链路路追踪中的实践 刘凯 七⽜牛云⼤大数据团队(Pandora)架构师 2.⾃自我介绍 INTRODUCTION • 刘凯,七⽜牛,⼤大数据Pandora团队成员 • 2015年年, ...

  7. 基于 SkyWalking 实现服务链路追踪

    https://blog.51cto.com/zero01/2463116 https://skywalking.apache.org/zh/blog/2019-03-29-introduction- ...

  8. 使用 Skywalking 实现全链路监控

    2017 年 10 月 29 日,又拍云 Open Talk 联合 Spring Cloud 中国社区成功举办了"进击的微服务实战派北京站".华为技术专家吴晟作了题为<使用 ...

  9. 前后端、多语言、跨云部署,全链路追踪到底有多难?

    作者|涯海 全链路追踪的价值 链路追踪的价值在于"关联",终端用户.后端应用.云端组件(数据库.消息等)共同构成了链路追踪的轨迹拓扑大图.这张拓扑覆盖的范围越广,链路追踪能够发挥的 ...

  10. mysql链路跟踪工具_SkyWalking全链路追踪利器

    随着目前系统架构的复杂度越来越高(中台.微服务),并且线上应用的多级监控覆盖到了通讯.应用处理过程监控并且实现端到端的应用监测,线上性能故障的快速定位修复:而传统的监控分析方式已经无法满足我们的需求, ...

最新文章

  1. Win7 wifi热点设置( 转载)
  2. ngx_lua中的协程调度(三)
  3. Akka并发编程——第二节:Actor模型(一)
  4. 计蒜客 A2232.程序设计:蒜厂年会-单调队列(双端队列(STL deque)实现)滑窗维护最小前缀和...
  5. Linux内核升级,从2.6.18升级到3.2.14
  6. Android 透明动画实现 详细概述
  7. 模拟image的ajaxPrefilter与ajaxTransport处理
  8. 远程注入利用远程线程直接注入
  9. WINDOWSXP全面优化
  10. Proteus、Keli对C51芯片实现仿真流水灯
  11. TPU原理技术与xPU
  12. VS2019创建COM组件
  13. 点击编辑按钮,前端table表格行内指定td可修改。(table是动态生成的)
  14. 你属于哪种性感女人?
  15. IDEA工具避坑指南(七):git@github.com: Permission denied|You must supply a key in OpenSSH public key format详解
  16. 『矩阵论笔记』详解最小二乘法(矩阵形式求导)+Python实战
  17. 华硕VIVO BOOK15s啃苹果之路
  18. GNU Radio入门之旅
  19. 给超链接加个手指的图标
  20. web渗透_一句话木马(webshell)_dvwa环境

热门文章

  1. Js 把html字符串显示,js Html结构转字符串形式显示代码
  2. 阿尔伯塔大学计算机科学是哪个校区,阿尔伯塔大学优势专业是什么?
  3. 基于RWEQ模型的土壤风蚀模数估算及其变化归因分析、RWEQ模型相关的SCI论文撰写技巧
  4. java处理图片的所有类_Java的图片处理工具类
  5. 游戏源代码是什么意思_什么是游戏
  6. 光耦p621引脚图_p421光耦引脚图和代换
  7. mybaties中resultMap和resultType的区别
  8. 新手学Unity3d的一些网站及相应学习路线
  9. 魔百和CM311-1a YST免拆机卡刷精简固件
  10. css中标准盒模型和怪异盒模型的区别,如何将标准盒模型转换为怪异盒模型