前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >技术阅读摘要-3.Jaeger技术分析

技术阅读摘要-3.Jaeger技术分析

作者头像
junedayday
发布2021-10-27 10:23:06
4680
发布2021-10-27 10:23:06
举报
文章被收录于专栏:Go编程点滴

概览

通过上一次技术阅读摘要,我们了解了分布式链路追踪这项技术,Jaeger是其主流的实现方案。

今天,我们就一起来看看Jaeger的相关资料,初步掌握这门技术。

官方资料

  • Jaeger官网 https://www.jaegertracing.io/
  • Github https://github.com/jaegertracing/jaeger
  • Dapper https://research.google/pubs/pub36356/
  • OpenZipkin https://zipkin.io/

核心概念

Jaeger的官方定义非常简洁 - Jaeger: open source, end-to-end distributed tracing

关键词是端到端的分布式追踪。怎么理解这个端到端呢?它更多地是关注分布式系统中的入和出。从一个HTTP服务来看,它关注的是请求和响应的具体数据。对应到如今k8s中盛行的sidecar模式,就是一个网络的sidecar,将所有的请求进行标注(如带上traceId)。

架构

Jaeger的官方文档上资料很丰富,更新也比较频繁。有些朋友会觉得阅读官方文档非常累,常常通篇阅读后发现抓不到重点、也没有什么印象。这里,我推荐一个页面 - https://www.jaegertracing.io/docs/1.27/architecture/ ,并结合我的理解,方便大家快速理解。

Span

Span是分布式链路追踪中一个通用的术语,字面翻译为 带名称的Jaeger逻辑单元

这里对逻辑单元的定义比较有争论,在我看来,逻辑单元的定义因具体场景而变化:

  • 在单体架构中,需要拆分成多个模块,每个模块定义成一个逻辑单元
  • 在一个简单的微服务中,可以将服务定义成一个逻辑单元
  • 在一个复杂的微服务中,可能需要根据更细的领域定义成一个逻辑单元

Trace

一个具体消息在整个分布式系统中的流转。

组件

Jaeger提供了2种架构的解决方案。我们先看看通用的部分:

  • jaeger-client作为具体语言的内部库,嵌入到应用程序中
  • jaeger-agent作为sidecar,部署在容器或机器上,用来从jaeger收集数据,并推送到jaeger collector
  • jaeger collector负责将数据保存到数据库或MQ中
  • jaeger-query + UI 查询并显示数据

而差异点就在于保存和分析数据的技术方案:

  • 简单方案:直接保存到数据库中,用Spark Jobs进行分析
  • 高性能方案:用Kafka来削峰填谷,用Flink流式计算提高性能

Jaeger Go

Trace的初始化

代码语言:javascript
复制
traceCfg := &jaegerconfig.Configuration{
  // 服务名
  ServiceName: "MyService",
  // 采样参数
  Sampler: &jaegerconfig.SamplerConfig{
    Type:  jaeger.SamplerTypeConst,
    Param: 1,
  },
  // 上报,这里通过jaeger sidecar的端口来上报日志
  Reporter: &jaegerconfig.ReporterConfig{
    LocalAgentHostPort: "127.0.0.1:6831",
    LogSpans:           true,
  },
}
// 初始化tracer
tracer, closer, err := traceCfg.NewTracer(jaegerconfig.Logger(jaeger.StdLogger))
if err != nil {
  panic(err)
}
defer closer.Close()
// 将tracer设置到opentracing的全局变量中
opentracing.SetGlobalTracer(tracer)

上面这段逻辑描述了 创建jaeger的tracer并保存到opentracing的全局变量中

这里强调一点:opentracing是一套标准,包括jaeger、zipkin等具体实现。我们可以深入看看NewTracer这个函数。它的注释很好地说明了这一点。具体的细节实现,我们暂时无需关注。

代码语言:javascript
复制
// Tracer implements opentracing.Tracer.
type Tracer struct {
}

技术组件引入Opentracing

通过上面的工作,我们已经在程序中引入了jaeger。但在实际的开发过程中,我们程序内部会有一些组件也需要引入jaeger的链路追踪,来实现更精细化的监控。

以gRPC-Gateway为例,引入Opentracing的链接如下:https://grpc-ecosystem.github.io/grpc-gateway/docs/operations/tracing/#opentracing-support 。这里面的代码可以直接引用,就不细看了。

目前,支持原生的Opentracing的组件越来越多。在引入一个复杂的组件时,我们要先了解清楚是否可以集成Opentracing,降低后续的运维复杂度。

提取TraceId信息

整个jaeger的引入并不复杂,就已经能很好地实现链路监控了。但在实际的开发过程中,我们仍有一个非常关键的需求:如何将一个请求的trace信息,引入到业务代码中,跟踪业务代码的处理过程。这一点,在debug问题时非常有意义,尤其是面对一些自己不太熟悉的代码。

开发人员面对这个场景,最常用的逻辑就是log,那就意味着我们要将traceid注入到日志中。那么怎么获取traceid呢?下面看一段示例代码:

代码语言:javascript
复制
// 从ctx获取span
if parent := opentracing.SpanFromContext(ctx); parent != nil {
  parentCtx := parent.Context()
  // 获取opentracing中的全局tracer
  if tracer := opentracing.GlobalTracer(); tracer != nil {
    mySpan := tracer.StartSpan("my info", opentracing.ChildOf(parentCtx))
    // 由于前面opentracing中的tracer是jaeger的,所以你这里转化为jaeger.SpanContext
    if sc, ok := mySpan.Context().(jaeger.SpanContext); ok {
      // 这里,就能获取traceid等信息了,可以放在日志里
      _ = sc.TraceID()
    }
    defer mySpan.Finish()
  }
}

逻辑就是从go语言的上下文context信息中,用Opentracing里定义的全局tracer,提取出traceId等信息。

总结

关于Jaeger内容有很多延伸点,但本文只作入门,点到即可。

如果只能记住一点,我希望大家能认识到:Jaeger是Opentracing标准的一个实现。从本文能看到,在标准统一后,具体实现的变更会变得非常简单:例如要将Jaeger替换成Zipkin,只需要初始化tracer处做到替换即可。

Github: https://github.com/Junedayday/code_reading Blog: http://junes.tech/ Bilibili: https://space.bilibili.com/293775192 公众号: golangcoding

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Go编程点滴 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概览
    • 官方资料
      • 核心概念
        • 架构
          • Span
          • Trace
          • 组件
        • Jaeger Go
          • Trace的初始化
          • 技术组件引入Opentracing
          • 提取TraceId信息
        • 总结
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档