在微服务为我们提供了模块分,低耦合的高效开发和DevOPS中,具体业务中当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。可能你会想在业务系统中请求中埋点,或写日志,但是这种都需要在业务代码中来写,而且耦合在代码中,不具备微服务的扩张性后后期的易维护行。
受Dapper和OpenZipkin启发的Jaeger是由Uber Technologies作为开源发布的分布式跟踪系统。它用于监视和诊断基于微服务的分布式系统,包括:
Jaeger后端的设计没有单点故障,可以根据业务需求进行扩展。例如,Uber上任何给定的Jaeger安装通常每天要处理数十亿个跨度。
Jaeger后端,Web UI和工具库已完全设计为支持OpenTracing标准。
通过跨度引用将迹线表示为有向无环图(不仅是树)
支持强类型的跨度标签和结构化日志通过行李
支持通用的分布式上下文传播机制
Jaeger支持两个流行的开源NoSQL数据库作为跟踪存储后端:Cassandra 3.4+和Elasticsearch 5.x / 6.x / 7.x。正在进行使用其他数据库的社区实验,例如ScyllaDB,InfluxDB,Amazon DynamoDB。Jaeger还附带了一个简单的内存存储区,用于测试设置。
Jaeger Web UI是使用流行的开源框架(如React)以Javascript实现的。v1.0中发布了几项性能改进,以允许UI有效处理大量数据,并显示具有成千上万个跨度的跟踪(例如,我们尝试了具有80,000个跨度的跟踪)。
Jaeger后端作为Docker映像的集合进行分发。这些二进制文件支持各种配置方法,包括命令行选项,环境变量和多种格式(yaml,toml等)的配置文件。Kubernetes模板和Helm图表有助于将其部署到Kubernetes集群。
默认情况下,所有Jaeger后端组件都公开Prometheus指标(也支持其他指标后端)。使用结构化日志库zap将日志写到标准输出。
Jaeger的第三方安全审核可在https://github.com/jaegertracing/security-audits中获得。有关Jaeger中可用安全机制的摘要,请参见问题#1718。
尽管我们建议使用OpenTracing API来对应用程序进行检测并绑定到Jaeger客户端库,以从其他地方无法获得的高级功能中受益,但是如果您的组织已经使用Zipkin库对检测进行了投资,则不必重写所有代码。Jaeger通过在HTTP上接受Zipkin格式(Thrift或JSON v1 / v2)的跨度来提供与Zipkin的向后兼容性。从Zipkin后端切换只是将流量从Zipkin库路由到Jaeger后端的问题。
您的应用程序必须经过检测,然后才能将跟踪数据发送到Jaeger后端。查看“客户端库”部分,以获取有关如何使用OpenTracing API以及如何初始化和配置Jaeger跟踪器的信息。
您的应用程序必须经过检测,然后才能将跟踪数据发送到Jaeger后端。查看“客户端库”部分,以获取有关如何使用OpenTracing API以及如何初始化和配置Jaeger跟踪器的信息。
多合一是用于快速本地测试的可执行文件,具有内存存储组件,可启动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) |
HotROD(按需乘车)是一个演示应用程序,由几个微服务组成,并说明了OpenTracing API的用法。博客文章中提供了一个教程/演练:以 OpenTracing API .的方式进行HotROD。它可以独立运行,但需要Jaeger后端才能查看跟踪。 Take OpenTracing for a HotROD ride
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 复制代码
docker run --rm -it / --link jaeger / -p8080-8083:8080-8083 / -e JAEGER_AGENT_HOST="jaeger" / jaegertracing/example-hotrod:1.14 / all 复制代码
Run example-hotrod(.exe)
executable from the binary distribution archives :
$ example-hotrod all 复制代码
Then navigate to http://localhost:8080
.
收集器服务公开了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 .
Span表示Jaeger中的逻辑工作单元,具有操作名称,操作的开始时间和持续时间。跨度可以嵌套并排序以建立因果关系模型。
每个 Span 包含以下对象:
跟踪是通过系统的数据/执行路径,可以看作跨度的有向无环图。
Jaeger可以作为多合一二进制(其中所有Jaeger后端组件都在单个进程中运行)进行部署,也可以作为可扩展的分布式系统进行部署,如下所述。有两个主要的部署选项:
本节详细介绍Jaeger的组成部分以及它们之间的关系。它由您的应用程序与之交互的顺序安排。
Jaeger客户端是OpenTracing API的特定于语言的实现。它们可用于手动或通过与OpenTracing集成的各种现有开源框架(例如Flask,Dropwizard,gRPC等)来检测应用程序以进行分布式跟踪。
检测服务在接收新请求时创建跨度,并将上下文信息(跟踪ID,跨度ID和行李)附加到传出请求。只有ID和行李随请求一起传播;不会传播构成跨度的所有其他信息,例如操作名称,日志等。取而代之的是,采样的跨度在后台异步传输到Jaeger Agents的过程外。
该仪器的开销很小,并且设计为始终在生产中启用。请注意,虽然生成了所有跟踪,但仅采样了一些。对跟踪进行采样将跟踪标记为进一步处理和存储。默认情况下,Jaeger客户端对0.1%的迹线进行采样(每1000个中的1个),并且能够从代理中检索采样策略。
Jaeger代理是一个网络守护程序,它侦听通过UDP发送的跨度,然后将其分批发送给收集器。它旨在作为基础结构组件部署到所有主机。该代理将收集器的路由和发现抽象到远离客户端的位置。
Jaeger收集器从Jaeger代理接收跟踪,并通过处理管道运行它们。当前,我们的管道会验证跟踪,为其建立索引,执行任何转换并最终存储它们。Jaeger的存储设备是可插拔组件,目前支持Cassandra,Elasticsearch和Kafka。
查询是一项从存储中检索跟踪并托管UI来显示跟踪的服务。
Ingesteris a service that reads from Kafka topic and writes to another storage backend (Cassandra, Elasticsearch).
Jaeger库实现了一致的前期(或基于头)的采样。例如,假设我们有一个简单的调用图,其中服务A调用服务B,服务B调用服务C:A-> B->C。当服务A收到不包含跟踪信息的请求时,Jaeger跟踪器将开始新的跟踪,为其分配一个随机跟踪ID,然后根据当前安装的采样策略做出采样决定。采样决策将与请求一起传播到B和C,因此这些服务将不会再次做出采样决策,而是会尊重顶级服务A做出的决策。这种方法保证了,如果对跟踪进行了采样,则所有其跨度将记录在后端。如果每个服务都做出自己的抽样决定,那么我们很少会在后端获得完整的跟踪。
使用配置对象实例化跟踪器时,可以通过sampler.type和sampler.param属性选择采样类型。Jaeger库支持以下采样器:
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
). 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. 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. 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 ). 自适应采样器是一个组合了两个功能的复合采样器:
可以静态配置每个操作参数,也可以在远程采样器的帮助下从Jaeger后端定期提取每个操作参数。自适应采样器旨在与Jaeger后端即将推出的自适应采样功能一起使用。
可以通过--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 } } 复制代码