安装jaeger

jaeger提供一个all in one 的docker镜像,可以快速搭建实验环境

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 16686:16686

-p 14268:14268

-p 9411:9411

jaegertracing/all-in-one:1.6

复制代码

OpenTracing

OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。 OpenTracing提供了用于运营支撑系统的和针对特定平台的辅助程序库。

jaeger兼容OpenTracing API,所以我们使用OpenTracing的程序库可以方便的替换追踪工具。

OpenTracing中文文档

jaeger使用

封住一下jaeger的初始化操作方便使用,详细用法可以查看 jaeger-client-go

// lib/tracer

// NewTracer 创建一个jaeger Tracer

func NewTracer(servicename string, addr string) (opentracing.Tracer, io.Closer, error) {

cfg := jaegercfg.Configuration{

ServiceName: servicename,

Sampler: &jaegercfg.SamplerConfig{

Type: jaeger.SamplerTypeConst,

Param: 1,

},

Reporter: &jaegercfg.ReporterConfig{

LogSpans: true,

BufferFlushInterval: 1 * time.Second,

},

}

sender, err := jaeger.NewUDPTransport(addr, 0)

if err != nil {

return nil, nil, err

}

reporter := jaeger.NewRemoteReporter(sender)

// Initialize tracer with a logger and a metrics factory

tracer, closer, err := cfg.NewTracer(

jaegercfg.Reporter(reporter),

)

return tracer, closer, err

}

func main() {

t, io, err := tracer.NewTracer("tracer", "")

if err != nil {

log.Fatal(err)

}

defer io.Close()

opentracing.SetGlobalTracer(t)

}

复制代码

opentracing.SetGlobalTracer(t) 方法执行会将jaeger tracer注册到全局,接下来只需要使用opentracing 的标准API便可以了。

如果不想使用jaeger了,想替换成其他分布式追踪工具,只需要工具支持opentracing标准,并将main函数的SetGlobalTracer操作替换即可,其他文件都不需要更改。

micro链路追踪插件

micro自带的opentracing插件

在micro自带的插件中已经有opentracing的插件了,包含server,client等,不过这个插件只能go-micro构建的微服务(api,srv)中使用。因为micro网关有一个独立的插件系统,但是并没有提供opentracing相关的插件。

micro/go-plugins/wrapper/trace/opentracing/opentracing.go

我们可以在构建服务的时候直接使用,只需要在服务初始化时增加一行函数就可以了。

service := micro.NewService(

micro.Name(name),

micro.Version("latest"),

micro.WrapHandler(ocplugin.NewHandlerWrapper(opentracing.GlobalTracer())),

)

复制代码

srv/user/main.go 目录下的user 服务是一个完整的使用实例。

为micro网关增加opentracing插件

实现原理

外部HTTP请求首先经过API网关,网关生成第一个SpanContexts并且通过HTTP头传递到聚合层的API服务,这边需要我们实现一个插件去做这件事,原理很简单,拦截每一次请求添加信息就可以了。

查看micro自带的opentracing插件,可以发现是通过golang的context传递,micro的RPC已经封装好了通过context在跨进程服务间传递SpanContexts机制,所以我们需要在API服务层实现一个插件,从HTTP头中取出SpanContexts并按照micro自带的方式注入golang context。

// micro opentracing插件中wHandlerWrappe

// NewHandlerWrapper accepts an opentracing Tracer and returns a Handler Wrapper

func NewHandlerWrapper(ot opentracing.Tracer) server.HandlerWrapper {

return func(h server.HandlerFunc) server.HandlerFunc {

return func(ctx context.Context, req server.Request, rsp interface{}) error {

name := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint())

ctx, span, err := traceIntoContext(ctx, ot, name)

if err != nil {

return err

}

defer span.Finish()

return h(ctx, req, rsp)

}

}

}

复制代码

micro API网关插件

lib/wrapper/tracer/opentracing/stdhttp/stdhttp.go

和实现JWT鉴权插件一样,实现一个HTTP中间件通过mciro的插件机制全局注册就可以实现拦截每次请求并处理。

// TracerWrapper tracer wrapper

func TracerWrapper(h http.Handler) http.Handler {

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

spanCtx, _ := opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header))

sp := opentracing.GlobalTracer().StartSpan(r.URL.Path, opentracing.ChildOf(spanCtx))

defer sp.Finish()

if err := opentracing.GlobalTracer().Inject(

sp.Context(),

opentracing.HTTPHeaders,

opentracing.HTTPHeadersCarrier(r.Header)); err != nil {

log.Println(err)

}

sct := &status_code.StatusCodeTracker{ResponseWriter: w, Status: http.StatusOK}

h.ServeHTTP(sct.WrappedResponseWriter(), r)

ext.HTTPMethod.Set(sp, r.Method)

ext.HTTPUrl.Set(sp, r.URL.EscapedPath())

ext.HTTPStatusCode.Set(sp, uint16(sct.Status))

if sct.Status >= http.StatusInternalServerError {

ext.Error.Set(sp, true)

}

})

}

复制代码Tracer相关的概念可以查看这个文档

opentracing.GlobalTracer().Extract 方法提取HTTP头中的spanContexts

opentracing.ChildOf 方法基于提取出来的spanContexts生成新的child spanContexts

opentracing.GlobalTracer().StartSpan 方法生成一个新的span

github.com/opentracing/opentracing-go/ext 通过ext可以为追踪添加一些tag来展示更多信息,比如URL,请求类型(GET,POST...), 返回码

sp.Finish() 结束这一个span

API服务(使用gin)插件

lib/wrapper/tracer/opentracing/gin2micro/gin2micro.go

// TracerWrapper tracer 中间件

func TracerWrapper(c *gin.Context) {

md := make(map[string]string)

spanCtx, _ := opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(c.Request.Header))

sp := opentracing.GlobalTracer().StartSpan(c.Request.URL.Path, opentracing.ChildOf(spanCtx))

defer sp.Finish()

if err := opentracing.GlobalTracer().Inject(sp.Context(),

opentracing.TextMap,

opentracing.TextMapCarrier(md)); err != nil {

log.Log(err)

}

ctx := context.TODO()

ctx = opentracing.ContextWithSpan(ctx, sp)

ctx = metadata.NewContext(ctx, md)

c.Set(contextTracerKey, ctx)

c.Next()

statusCode := c.Writer.Status()

ext.HTTPStatusCode.Set(sp, uint16(statusCode))

ext.HTTPMethod.Set(sp, c.Request.Method)

ext.HTTPUrl.Set(sp, c.Request.URL.EscapedPath())

if statusCode >= http.StatusInternalServerError {

ext.Error.Set(sp, true)

}

}

// ContextWithSpan 返回context

func ContextWithSpan(c *gin.Context) (ctx context.Context, ok bool) {

v, exist := c.Get(contextTracerKey)

if exist == false {

ok = false

return

}

ctx, ok = v.(context.Context)

return

}

复制代码

基本操作流程和给micro编写的插件相同,但是有两点不同。其一,因为我使用gin开发API服务,所以基于gin的API。其二,因为micro内部提供通过golang context传递spanContexts的机制,所以将这边会将child spanContexts注入到gin 的context,在API服务通过micro提供RPC接口(生成的XX.micro.go文件中调用函数第一个参数都是context)调用其他服务时传入提取的context,如下:

...

ctx, ok := gin2micro.ContextWithSpan(c)

if ok == false {

log.Log("get context err")

}

res, err := s.helloC.Call(ctx, &helloS.Request{Name: "xuxu"})

...

复制代码

完整的实现细节可以查看,github仓库中 lib/wrapper/tracer/opentracing, 这里。

完整体验

项目完整代码地址

go 链路追踪_【go-micro实践】jaeger分布式链路追踪相关推荐

  1. jaeger分布式链路追踪

    推荐去官网系统的了解一下 https://www.jaegertracing.io 随着应用容器化和微服务的兴起,借由Docker和 Kubernetes 等工具, 服务的快速开发和部署成为可能,构建 ...

  2. java全链路监控_使用SkyWalking+elasticsearch实现全链路监控

    面对以上情况, 我们就需要一些可以帮助理解系统行为.用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题.这时候分布式追踪系统就该闪亮登场了. 一.分布式追踪系统skywalking 1 ...

  3. od 追踪_裁判员行为规范【基本功】——追踪裁判违例宣判练习 /五秒违例

    当打出一个违例手势后,固定它,并在你的脑海里默念一两秒.要求有力,干脆,清晰和果断的手势. 手势程序:⑴停表手势,(2)取消得分手势 / 口语并用 / 如需要),⑶对应的违例手势 / 口语并用,⑷比赛 ...

  4. 儿童手表运动轨迹和路径追踪_如何将智能手表或健身追踪器用作静音闹钟

    儿童手表运动轨迹和路径追踪 When you need to wake up without disturbing everyone around you a silent vibration-bas ...

  5. od 追踪_裁判员行为规范【基本功】——追踪裁判违例宣判练习 / 脚踢球违例

    当打出一个违例手势后,固定它,并在你的脑海里默念一两秒.要求有力,干脆,清晰和果断的手势. 手势程序:⑴停表手势,(2)取消得分手势 / 口语并用 / 如需要),⑶对应的违例手势 / 口语并用,⑷比赛 ...

  6. od 追踪_裁判员行为规范【基本功】——追踪裁判违例宣判练习 / 带球走违例

    当打出一个违例手势后,固定它,并在你的脑海里默念一两秒.要求有力,干脆,清晰和果断的手势. 手势程序:⑴停表手势,(2)取消得分手势 / 口语并用 / 如需要),⑶对应的违例手势 / 口语并用,⑷比赛 ...

  7. od 追踪_裁判员行为规范【基本功】——追踪裁判违例宣判练习 / 两次运球违例...

    当打出一个违例手势后,固定它,并在你的脑海里默念一两秒.要求有力,干脆,清晰和果断的手势. 手势程序:⑴停表手势,(2)取消得分手势 / 口语并用 / 如需要),⑶对应的违例手势 / 口语并用,⑷比赛 ...

  8. Pinpoint详解(分布式链路追踪、链路监控)

    英文原文:https://naver.github.io/pinpoint/1.8.4/techdetail.html 说明:[]中内容为方便解释自己加的 在这篇文章中,我们描述了Pinpoint的技 ...

  9. 分布式服务追踪与调用链系统

    如何构建新一代SkyWalking服务追踪框架 1.生产环境调用接口报错了,如何定位? 2.微服务服务追踪框架构设计原理 3.Sleuth+zipkin实现分布式服务追踪 4.SkyWalking超强 ...

最新文章

  1. 【CV】使用Keras和迁移学习从人脸图像中预测体重指数BMI
  2. oracle查询 :一个角色包括的系统权限,对象权限,Oracle有多少种角色,某个用户有什么角色
  3. Linux命令工作中常用的总结
  4. fat32 linux 打包工具_一个方便的用于创建树莓派 SD 卡镜像的程序 | Linux 中国
  5. SVN:show log问题
  6. python wordcloud下载_Python数据可视化之Wordcloud
  7. 地图结合资料 提供全新网络服务
  8. 通过OpenSSL创建自签名证书在Flask实现HTTPS
  9. 有点理解Google为什么要退出中国市场了
  10. Ctrl+Shift+F 输入法变成繁体 输入法简体繁体切换
  11. 帆软折线图设置红色警戒线
  12. linux搭建http代理服务器
  13. 如何将一个div水平垂直居中?6种方法做推荐
  14. 在传统软件公司十年深恶痛绝的感受
  15. 一名合格的Java后端工程师或架构师必须要掌握 Spring Framework、Spring Boot、Spring Cloud
  16. 天梯赛:L2-016 愿天下有情人都是失散多年的兄妹 (25 分)
  17. 自定义view实现涂鸦(画板)功能
  18. 域控服务器的dns配置,如何配置额外域控制器上的DNS?
  19. Zotero(1)---文献管理软件Zotero安装教程
  20. 亿级用户体量,千万级日活用户,《王者荣耀》高并发背后的故事!

热门文章

  1. 博客搭建攻略(三):创造收益
  2. ajax为什么会全局刷新,为什么发送ajax请求页面也会刷新呢?
  3. TP-GAN 侧脸修复
  4. libxml/xmlversion.h: No such file or directory
  5. Python 进程之间共享数据(全局变量)
  6. python与caffe改变通道顺序
  7. python 逻辑回归
  8. dw读取access中的图片_怎样从Access数据库中读取图片?解决办法
  9. maven java 可执行jar_Maven项目打包成可执行Jar文件
  10. html 字号自适应,自适应网页中字体大小自适应屏幕 - YangJunwei