微服务链路追踪之Jaeger

举报
kaliarch 发表于 2021/11/20 20:46:03 2021/11/20
【摘要】 一 Jaeger概述在微服务为我们提供了模块分,低耦合的高效开发和DevOPS中,具体业务中当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。可能你会想在业务系统中请求中埋点,或写日志,但是这种都需要在业务代码中来写,而且耦合在代码中,不具备微服务的扩张性后后期的易维护行。 1.1 Jaeger概念受Dapper和OpenZipk...

一 Jaeger概述

在微服务为我们提供了模块分,低耦合的高效开发和DevOPS中,具体业务中当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。可能你会想在业务系统中请求中埋点,或写日志,但是这种都需要在业务代码中来写,而且耦合在代码中,不具备微服务的扩张性后后期的易维护行。

1.1 Jaeger概念

受Dapper和OpenZipkin启发的Jaeger是由Uber Technologies作为开源发布的分布式跟踪系统。它用于监视和诊断基于微服务的分布式系统,包括:

  • 分布式上下文传播
  • 分布式交易监控
  • 根本原因分析
  • 服务依赖性分析性能/延迟优化

1.2 特性

1.2.1 高扩展性

Jaeger后端的设计没有单点故障,可以根据业务需求进行扩展。例如,Uber上任何给定的Jaeger安装通常每天要处理数十亿个跨度。

1.2.2 原生支持OpenTracing

Jaeger后端,Web UI和工具库已完全设计为支持OpenTracing标准。

  • 通过跨度引用将迹线表示为有向无环图(不仅是树)

  • 支持强类型的跨度标签和结构化日志通过行李

  • 支持通用的分布式上下文传播机制

1.2.3 多存储后端

Jaeger支持两个流行的开源NoSQL数据库作为跟踪存储后端:Cassandra 3.4+和Elasticsearch 5.x / 6.x / 7.x。正在进行使用其他数据库的社区实验,例如ScyllaDB,InfluxDB,Amazon DynamoDB。Jaeger还附带了一个简单的内存存储区,用于测试设置。

1.2.4 现代化的UI

Jaeger Web UI是使用流行的开源框架(如React)以Javascript实现的。v1.0中发布了几项性能改进,以允许UI有效处理大量数据,并显示具有成千上万个跨度的跟踪(例如,我们尝试了具有80,000个跨度的跟踪)。

1.2.5 云原生部署

Jaeger后端作为Docker映像的集合进行分发。这些二进制文件支持各种配置方法,包括命令行选项,环境变量和多种格式(yaml,toml等)的配置文件。Kubernetes模板和Helm图表有助于将其部署到Kubernetes集群。

1.2.6 可观察性

默认情况下,所有Jaeger后端组件都公开Prometheus指标(也支持其他指标后端)。使用结构化日志库zap将日志写到标准输出。

1.2.7 安全

Jaeger的第三方安全审核可在https://github.com/jaegertracing/security-audits中获得。有关Jaeger中可用安全机制的摘要,请参见问题#1718。

1.2.8 与Zipkin的向后兼容性

尽管我们建议使用OpenTracing API来对应用程序进行检测并绑定到Jaeger客户端库,以从其他地方无法获得的高级功能中受益,但是如果您的组织已经使用Zipkin库对检测进行了投资,则不必重写所有代码。Jaeger通过在HTTP上接受Zipkin格式(Thrift或JSON v1 / v2)的跨度来提供与Zipkin的向后兼容性。从Zipkin后端切换只是将流量从Zipkin库路由到Jaeger后端的问题。

二 快速入门

您的应用程序必须经过检测,然后才能将跟踪数据发送到Jaeger后端。查看“客户端库”部分,以获取有关如何使用OpenTracing API以及如何初始化和配置Jaeger跟踪器的信息。

2.1 简介

您的应用程序必须经过检测,然后才能将跟踪数据发送到Jaeger后端。查看“客户端库”部分,以获取有关如何使用OpenTracing API以及如何初始化和配置Jaeger跟踪器的信息。

2.2 All in One

多合一是用于快速本地测试的可执行文件,具有内存存储组件,可启动Jaeger UI,收集器,查询和代理。开始多合一的最简单方法是使用发布到DockerHub的预构建映像(单个命令行)。

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.14

Or run the jaeger-all-in-one(.exe) executable from the binary distribution archives:

jaeger-all-in-one --collector.zipkin.http-port=9411

You can then navigate to http://localhost:16686 to access the Jaeger UI.

容器需要暴露的端口

Port Protocol Component Function
5775 UDP agent accept zipkin.thrift over compact thrift protocol (deprecated, used by legacy clients only)
6831 UDP agent accept jaeger.thrift over compact thrift protocol
6832 UDP agent accept jaeger.thrift over binary thrift protocol
5778 HTTP agent serve configs
16686 HTTP query serve frontend
14268 HTTP collector accept jaeger.thrift directly from clients
14250 HTTP collector accept model.proto
9411 HTTP collector Zipkin compatible endpoint (optional)

2.3 Kubernetes and OpenShift

2.4 示例APP:HotROD

HotROD(按需乘车)是一个演示应用程序,由几个微服务组成,并说明了OpenTracing API的用法。博客文章中提供了一个教程/演练:以OpenTracing API.的方式进行HotROD。它可以独立运行,但需要Jaeger后端才能查看跟踪。Take OpenTracing for a HotROD ride

2.4.1 特性

  • 通过数据驱动的依赖关系图发现整个系统的体系结构
  • 查看请求时间表和错误;了解应用程序的工作方式。
  • 查找延迟和缺乏并发的来源。
  • 高度上下文化的日志记录。
  • 使用行李传播来:
    • 诊断请求间争用(排队)。
    • 服务花费的属性时间
  • 将开源库与OpenTracing集成一起使用可免费获得与供应商无关的工具。

2.4.2 先决条件

  • 您需要在计算机上安装Go 1.11或更高版本才能从源代码运行
  • 需要运行的Jaeger后端才能查看跟踪

2.4.3 运行

2.4.3.1 源码

mkdir -p $GOPATH/src/github.com/jaegertracing
cd $GOPATH/src/github.com/jaegertracing
git clone git@github.com:jaegertracing/jaeger.git jaeger
cd jaeger
make install
go run ./examples/hotrod/main.go all

2.4.3.2 docker

docker run --rm -it \
  --link jaeger \
  -p8080-8083:8080-8083 \
  -e JAEGER_AGENT_HOST="jaeger" \
  jaegertracing/example-hotrod:1.14 \
  all

2.4.3.3 二进制

Run example-hotrod(.exe) executable from the binary distribution archives:

$ example-hotrod all

Then navigate to http://localhost:8080.

2.5 从Zipkin迁移

收集器服务公开了Zipkin兼容的REST API / api / v1 / spans,该API接受Thrift和JSON。此外,还有/ api / v2 / spans用于JSON和Proto。默认情况下,它是禁用的。可以使用–collector.zipkin.http-port = 9411启用它

Zipkin Thrift IDL and Zipkin Proto IDL files can be found in jaegertracing/jaeger-idl repository. They’re compatible with openzipkin/zipkin-api Thrift and Proto.

三 架构

3.1 术语

3.1.1 Span

Span表示Jaeger中的逻辑工作单元,具有操作名称,操作的开始时间和持续时间。跨度可以嵌套并排序以建立因果关系模型。

图片描述

每个 Span 包含以下对象:

  • Operation name:操作名称 (也可以称作 Span name)。
  • Start timestamp:起始时间。
  • Finish timestamp:结束时间。
  • Span tag:一组键值对构成的 Span 标签集合。键值对中,键必须为 String,值可以是字符串、布尔或者数字类型。
  • Span log:一组 Span 的日志集合。每次 Log 操作包含一个键值对和一个时间戳。键值对中,键必须为 String,值可以是任意类型。
  • SpanContext: pan 上下文对象。每个 SpanContext 包含以下状态:
    • 要实现任何一个 OpenTracing,都需要依赖一个独特的 Span 去跨进程边界传输当前调用链的状态(例如:Trace 和 Span 的 ID)。
    • Baggage Items 是 Trace 的随行数据,是一个键值对集合,存在于 Trace 中,也需要跨进程边界传输。
  • References(Span 间关系):相关的零个或者多个 Span(Span 间通过 SpanContext 建立这种关系)。

3.1.2 Trace

跟踪是通过系统的数据/执行路径,可以看作跨度的有向无环图。

3.2 组件

Jaeger可以作为多合一二进制(其中所有Jaeger后端组件都在单个进程中运行)进行部署,也可以作为可扩展的分布式系统进行部署,如下所述。有两个主要的部署选项:

  • 收集器正在直接写入存储。

图片描述

  • 收集器正在写信给Kafka作为初步缓冲。

图片描述

本节详细介绍Jaeger的组成部分以及它们之间的关系。它由您的应用程序与之交互的顺序安排。

3.2.1 Jaeger client libraries

Jaeger客户端是OpenTracing API的特定于语言的实现。它们可用于手动或通过与OpenTracing集成的各种现有开源框架(例如Flask,Dropwizard,gRPC等)来检测应用程序以进行分布式跟踪。

检测服务在接收新请求时创建跨度,并将上下文信息(跟踪ID,跨度ID和行李)附加到传出请求。只有ID和行李随请求一起传播;不会传播构成跨度的所有其他信息,例如操作名称,日志等。取而代之的是,采样的跨度在后台异步传输到Jaeger Agents的过程外。

该仪器的开销很小,并且设计为始终在生产中启用。请注意,虽然生成了所有跟踪,但仅采样了一些。对跟踪进行采样将跟踪标记为进一步处理和存储。默认情况下,Jaeger客户端对0.1%的迹线进行采样(每1000个中的1个),并且能够从代理中检索采样策略。

图片描述

3.2.2 Agent

Jaeger代理是一个网络守护程序,它侦听通过UDP发送的跨度,然后将其分批发送给收集器。它旨在作为基础结构组件部署到所有主机。该代理将收集器的路由和发现抽象到远离客户端的位置。

3.2.3 Collector

Jaeger收集器从Jaeger代理接收跟踪,并通过处理管道运行它们。当前,我们的管道会验证跟踪,为其建立索引,执行任何转换并最终存储它们。Jaeger的存储设备是可插拔组件,目前支持Cassandra,Elasticsearch和Kafka。

3.2.4 Query

查询是一项从存储中检索跟踪并托管UI来显示跟踪的服务。

3.2.5 Ingester

Ingester is a service that reads from Kafka topic and writes to another storage backend (Cassandra, Elasticsearch).

3.3 Sampling

Jaeger库实现了一致的前期(或基于头)的采样。例如,假设我们有一个简单的调用图,其中服务A调用服务B,服务B调用服务C:A-> B->C。当服务A收到不包含跟踪信息的请求时,Jaeger跟踪器将开始新的跟踪,为其分配一个随机跟踪ID,然后根据当前安装的采样策略做出采样决定。采样决策将与请求一起传播到B和C,因此这些服务将不会再次做出采样决策,而是会尊重顶级服务A做出的决策。这种方法保证了,如果对跟踪进行了采样,则所有其跨度将记录在后端。如果每个服务都做出自己的抽样决定,那么我们很少会在后端获得完整的跟踪。

3.3.1 客户端采样配置

使用配置对象实例化跟踪器时,可以通过sampler.type和sampler.param属性选择采样类型。Jaeger库支持以下采样器:

  • Constant (sampler.type=const) sampler always makes the same decision for all traces. It either samples all traces (sampler.param=1) or none of them (sampler.param=0).
  • Probabilistic (sampler.type=probabilistic) sampler makes a random sampling decision with the probability of sampling equal to the value of sampler.param property. For example, with sampler.param=0.1 approximately 1 in 10 traces will be sampled.
  • Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate limiter to ensure that traces are sampled with a certain constant rate. For example, when sampler.param=2.0 it will sample requests with the rate of 2 traces per second.
  • Remote (sampler.type=remote, which is also the default) sampler consults Jaeger agent for the appropriate sampling strategy to use in the current service. This allows controlling the sampling strategies in the services from a central configuration in Jaeger backend, or even dynamically (see Adaptive Sampling).

3.3.2 适配示例

自适应采样器是一个组合了两个功能的复合采样器:

  • 它基于每个操作(即基于跨度操作名称)做出抽样决策。这在API服务中尤其有用,这些API服务的端点的流量可能非常不同,并且对整个服务使用单个概率采样器可能会使某些低QPS端点饿死(从不采样)。
  • 它支持最低的保证采样率,例如始终允许每秒最多N条迹线,然后以一定的概率对所有采样率进行采样(一切都是针对每个操作,而非针对每个服务)。

可以静态配置每个操作参数,也可以在远程采样器的帮助下从Jaeger后端定期提取每个操作参数。自适应采样器旨在与Jaeger后端即将推出的自适应采样功能一起使用。

3.3.3 集合示例配置

可以通过–sampling.strategies-file选项使用静态采样策略实例化收集器(如果使用Remote sampler配置,则将其传播到相应的服务)。此选项需要一个已定义采样策略的json文件路径。

{
  "service_strategies": [
    {
      "service": "foo",
      "type": "probabilistic",
      "param": 0.8,
      "operation_strategies": [
        {
          "operation": "op1",
          "type": "probabilistic",
          "param": 0.2
        },
        {
          "operation": "op2",
          "type": "probabilistic",
          "param": 0.4
        }
      ]
    },
    {
      "service": "bar",
      "type": "ratelimiting",
      "param": 5
    }
  ],
  "default_strategy": {
    "type": "probabilistic",
    "param": 0.5
  }
}

四 示例测试

访问:http://139.9.163.110:8080/

图片描述

图片描述

图片描述

代码示例可参考一位go大佬的一个示例:https://github.com/xinliangnote/go-gin-api

参考链接

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。