首页 > 其他分享 >链路跟踪Jaeger使用总结

链路跟踪Jaeger使用总结

时间:2022-12-27 20:05:59浏览次数:55  
标签:Span 0.0 jaeger Jaeger 跟踪 链路 埋点


背景

当系统架构变得越来越复杂后,我们一次前端请求,有可能要经历跨多个线程/跨多个协程/跨多个进程处理后,才会最终响应到客户端,如果请求按照预期正确执行还好,万一在某个调用链的某一环节出现了问题,排查起来非常的麻烦,但如果有链路跟踪的话,就会大大降低排查的困难度。
可以通过在关键点设置链路埋点,记录下重要的步骤,例如,请求接收处,逻辑处理处,数据库交互处,调用了外部服务等。

在阅读本文章之前,大家需要有链路跟踪的基础知识,这个可以查看我另一篇文章:​​我眼中的OpenTracing​​

前言

Jaeger是一款广受欢迎的开源分布式链路跟踪系统,兼容OpenTracing API,且已加入CNCF开源组织。其主要功能是聚合来自各个异构系统的实时监控数据。对一些常用的框架通过插件可以达到无侵入式跟踪,比如Apache HttpClient,Elasticsearch,JDBC,Kafka,Memcached,Mongo,OkHttp,Redis,Spring Boot,Spring Cloud,要通过Jaeger将Java应用数据上报至链路追踪控制台,首先需要完成埋点工作。您可以手动埋点,也可以利用各种现有插件实现埋点的目的。本文介绍以下三种埋点方法的其中一种手动埋点。

  1. 手动埋点
  2. 通过Spring Cloud组件埋点
  3. 通过gRPC组件埋点

一、Jaeger 是什么?

由于 Uber 的业务增长迅猛,其软件架构也越来越复杂,截止 2015 年下半年,Uber 内部已经有 500 多个微服务在运行,给问题排查和性能分析带来巨大困难。2016 年 4 月,Uber 启动 Jaeger 项目,并逐渐在内部推行分布式追踪系统,一年之后(2017 年 4 月),Uber 宣布正式将 Jaeger 开源。Uber Engineering Blog 有一篇文章介绍了分布式追踪系统在 Uber 的演进过程,建议阅读,《Evolving Distributed Tracing at Uber Engineering》。Uber开源的Jaeger(发音为ˈyā-gər ),因为它对OpenTracing支持的比较好,而且部署使用也非常简单。另外Jaeger的作者就是Yurishkuro。这里就不介绍Jaeger的细节了,有兴趣的可以去官网了解:​​Jaeger官网​​。

链路跟踪Jaeger使用总结_java


按照数据流向,整体可以分为四个部分:

jaeger-client:Jaeger 的客户端,实现了 OpenTracing 的 API,支持主流编程语言。客户端直接集成在目标 Application 中,其作用是记录和发送 Span 到 Jaeger Agent。在 Application 中调用 Jaeger Client Library 记录 Span 的过程通常被称为埋点。

jaeger-agent:暂存 Jaeger Client 发来的 Span,并批量向 Jaeger Collector 发送 Span,一般每台机器上都会部署一个 Jaeger Agent。官方的介绍中还强调了 Jaeger Agent 可以将服务发现的功能从 Client 中抽离出来,不过从架构角度讲,如果是部署在 Kubernetes 或者是 Nomad 中,Jaeger Agent 存在的意义并不大。

jaeger-collector:接受 Jaeger Agent 发来的数据,并将其写入存储后端,目前支持采用 Cassandra 和 Elasticsearch 作为存储后端。个人还是比较推荐用 Elasticsearch,既可以和日志服务共用同一个 ES,又可以使用 Kibana 对 Trace 数据进行额外的分析。架构图中的存储后端是 Cassandra,旁边还有一个 Spark,讲的就是可以用 Spark 等其他工具对存储后端中的 Span 进行直接分析。
jaeger-query & jaeger-ui:读取存储后端中的数据,以直观的形式呈现。

Jaeger 的架构非常清晰,部署起来也很轻松,Docker Hub 中有官方打好的 Image,可以拿来直接用,https://hub.docker.com/u/jaegertracing/。如果是本地测试,可以直接用 Jaeger 的 all-in-one Image,


上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是,SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。
Jaeger receiver
Jaeger receiver 目前只在跟踪模式下工作,不支持分析模式。Jaeger receiver提供额外的GRPC主机/端口,如果没有,将使用共享服务器主机/端口,还没有就使用核心GRPC主机/端口。Receiver需要激活Jaeger ElasticSearch存储实现。阅读此内容了解如何激活。right now only works in Tracing Mode, and no analysis. Jaeger receiver provides extra gRPC host/port, if absent, sharing-server host/port will be used, then core gRPC host/port. Receiver requires jaeger-elasticsearch storage implementation active. Read this to know how to active.

现在,你需要jaeger agent 来批量发送spans到 SkyWalking的oap服务器。 阅读Jaeger Architecture获取更多详情。

激活这个receiver。

receiver_jaeger:
default:
gRPCHost: ${SW_RECEIVER_JAEGER_HOST:0.0.0.0}
gRPCPort: ${SW_RECEIVER_JAEGER_PORT:14250}
  • 下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
  • 右部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。
  • 左部分 SkyWalking UI :负责提供控台,查看链路等等。

二、使用步骤

1.引入库

api group: 'io.jaegertracing', name: 'jaeger-client', version: '1.6.0';
api group: 'io.opentracing', name: 'opentracing-api', version: '0.33.0';
api group: 'io.opentracing', name: 'opentracing-util', version: '0.33.0';

2.配置初始化参数

public void init(String serverName, String agentIp, int agentPort, int ratingLimit) {
logger.info("init tracer client start,serverName={},agentIp={},agentPort={}", serverName, agentIp, agentPort);
Configuration config = new Configuration(serverName);
SenderConfiguration sender = new SenderConfiguration();
sender.withAgentHost(agentIp);
sender.withAgentPort(agentPort);
//一秒钟最多1000次采样
if (ratingLimit == 0) {
ratingLimit = 1000;
}
config.withSampler(new SamplerConfiguration().withType(RateLimitingSampler.TYPE).withParam(ratingLimit));
//全量采集,采样率设置0,1 分别对应打开和关闭
// config.withSampler(new SamplerConfiguration().withType(ConstSampler.TYPE).withParam(1));
config.withReporter(new ReporterConfiguration().withSender(sender).withMaxQueueSize(10000).withFlushInterval(60000));
config.withCodec(new CodecConfiguration().withBinaryCodec(Format.Builtin.BINARY, new BinaryCodec()));
GlobalTracer.registerIfAbsent(config.getTracer());
logger.info("init tracer client end,serverName={},agentIp={},agentPort={}", serverName, agentIp, agentPort);
}

如何设置埋点?

/**
* 开启链路
*/
public Span startTrace(SpanContext context, String methodName) {
if (methodName == null) {
return null;
}
Tracer tracer = GlobalTracer.get();
SpanBuilder spanBuilder = tracer.buildSpan(methodName);
String traceId = ThreadContext.get(SystemConstant.TRACE_ID);
if (traceId != null) {
spanBuilder.withTag("userId", traceId);
}

String threadName = "";
if (Thread.currentThread().isVirtual()) {
spanBuilder.withTag(SystemConstant.VIRTUAL_KEY, true);
threadName = "[" + Thread.currentThread().getName() + "]";
} else {
spanBuilder.withTag(SystemConstant.VIRTUAL_KEY, false);
threadName = Thread.currentThread().getName();
}
spanBuilder.withTag(SystemConstant.THREAD_KEY, threadName);
// Tags.SPAN_KIND_SERVER;
if (context != null) {
spanBuilder.asChildOf(context);
}
Span span = spanBuilder.start();
return span;

}

//埋点

Span span = TraceService.getInstance().startTrace(methodName);
try (Scope scope = GlobalTracer.get().activateSpan(span)) {
span.setTag("message", this.getName());
//handle your business
} catch (Exception e) {
TracingHelper.onError(e, span);
} finally {
span.finish();
}

批量上报的线程如下:

链路跟踪Jaeger使用总结_ci_02


上报的类 :io.jaegertracing.internal.reporters.RemoteReporter

上报的方法在io.jaegertracing.internal.reporters.RemoteReporter.QueueProcessor#run
如果要把上报的日志打开
则要做如下设置:
new ReporterConfiguration().withLogSpans(true)
则会有如下的日志输出

2021-12-31 14:44:01.734 INFO [game-bus-cache-1][worker-0][LoggingReporter.java:43]29a998394fc0478c869ce7aba3623688 - Span reported: 015dcaea33775a88:015dcaea33775a88:0:1 - UserController.handle(GetAccountList_C2S_Msg)
public class LoggingReporter implements Reporter {
private final Logger logger;

public LoggingReporter() {
this(null);
}

public LoggingReporter(Logger logger) {
if (logger == null) {
logger = LoggerFactory.getLogger(this.getClass());
}
this.logger = logger;
}

@Override
public void report(JaegerSpan span) {
logger.info("Span reported: {}", span);
}

@Override
public void close() {
// nothing to do
}
}

2.读入数据

链路跟踪Jaeger使用总结_链路_03


链路跟踪Jaeger使用总结_分布式_04

3.对外端口

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)

查看运行中的容器实例:

doker ps

查看所有容器实例,包括没有运行的:

[root@skywalking ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5181eab3c173 jaegertracing/all-in-one:1.27 "/go/bin/all-in-one-…" 2 hours ago Up 2 hours 5775/udp, 5778/tcp, 14250/tcp, 6832/udp, 14268/tcp, 0.0.0.0:6831->6831/udp, 0.0.0.0:16686->16686/tcp silly_bardeen```

root 25723 26830 0 15:48 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 16686 -container-ip 172.17.0.2 -container-port 16686
root 25737 26830 0 15:48 ? 00:00:00 /usr/bin/docker-proxy -proto udp -host-ip 0.0.0.0 -host-port 6831 -container-ip 172.17.0.2 -container-port 6831

你可以通过访问 http://localhost:16686 展示 Jaeger UI.

采样速率
支持设置采样率是 Jaeger 的一个亮点,生产环境系统性能很重要,所以对于所有的请求都开启 Trace 显然会带来比较大的压力,另外,大量的数据也会带来很大存储压力。为了尽量消除分布式追踪采样对系统带来的影响,设置采样率是一个很好的办法。Jaeger官方 支持四种采样类别,分别是 const、probabilistic、rateLimiting 和 remote

const:全量采集,采样率设置0,1 分别对应打开和关闭
probabilistic:概率采集,默认万份之一,取值可在 0 至 1 之间,例如设置为 0.5 的话意为只对 50% 的请求采样
rateLimiting:限速采集,每秒只能采集一定量的数据,如设置2的话,就是每秒采集2个链路数据
remote :是遵循远程设置,取值的含义和 probabilistic 相同,都意为采样的概率,只不过设置为 remote 后,Client 会从 Jaeger Agent 中动态获取采样率设置。
guaranteedThroughput:复合采样,至少每秒采样lowerBound次(rateLimiting),超过lowerBound次的话,按照samplingRate概率来采样(probabilistic),

链路跟踪Jaeger使用总结_ci_05

看了代码,还有两个复合采样器,GuaranteedThroughputSampler 和 PerOperationSampler

总结

总之,Jaeger链路跟踪有很多值得我们学习的地方。

参考链接:
​​​The OpenTracing Semantic Specification​

​OpenTracing Java Library教程​

​Opentracing 链路追踪实战​

​阿里云链路追踪 Tracing Analysis通过 Jaeger 上报 Java 应用数据​

​Sampling​

​Jaeger Tracing 采样算法分析​


标签:Span,0.0,jaeger,Jaeger,跟踪,链路,埋点
From: https://blog.51cto.com/u_4176761/5973452

相关文章

  • 全链路实时监控--istio
    提供一种简单的方式来为已部署的服务建立网络,该网络具有负载均衡、服务间认证、监控等功能,而不需要对服务的代码做任何改动。 istio适用于容器或虚拟机环境(特别是k8s),兼容......
  • 从三万英尺看全链路灰度
    作者:卜比全链路灰度是微服务领域,很实用的企业级场景下的技术能力。从本期开始,我们将通过《全链路灰度:自顶向下的方法》的系列文章,由远及近的剖析全链路灰度全貌,系列文章分为......
  • Jaeger&ElasticSearch存储链路追踪数据
    前言Jaeger的allinone镜像下是用内存存储(或是临时文件格式存储),容器重启,数据丢失。生产环境下更多是存储到es或是cassandra,这样对于查询或是系统扩展是比较方便的。此......
  • m基于MATLAB的上行链路MIMO关键技术的研究与性能分析
    1.算法概述       多输入多输出(MIMO)天线技术的巨大潜力为新一代无线通信技术的研究提供了广阔的舞台。近年来,多用户的MIMO研究逐渐成为热点问题。针对多用户的MI......
  • m基于MATLAB的上行链路MIMO关键技术的研究与性能分析
    1.算法概述多输入多输出(MIMO)天线技术的巨大潜力为新一代无线通信技术的研究提供了广阔的舞台。近年来,多用户的MIMO研究逐渐成为热点问题。针对多用户的MIMO,天线选择和用......
  • 性能跟踪
    前端性能点渲染mvvm,ssrc请求request,服务器  渲染优化action(批量界面渲染)runInActionvssetState(batchUpdate)runInScenariothis.form.select('name').value='......
  • C++11:返回值类型后置(跟踪返回值类型)
    返回值类型后置语法,是为了解决函数返回值类型依赖于参数而导致难以确定返回值类型的问题。有了这种语法以后,对返回值类型的推导就可以用清晰的方式(直接通过参数做运算)描述......
  • Day10_11_消息队列之保证RabbitMQ全链路数据完全不丢失
    保证RabbitMQ全链路数据完全不丢失一.消息可靠性概述1.消息生命周期过程一条消息从创建到最终被消费掉,也就是从生产端到消费端最终被消费掉大致上要经过3个步骤:1️⃣.生产......
  • 基于YOLOv5实现集装箱检测跟踪
     首先展示下效果(cpu下),电脑配置如下,win10操作系统   最终的效果   下面进入实际操作1.安装anaconda与pycharm(不会可以百度下)2.运行anaconda 3......
  • 链路追踪-Google-Dapper论文翻译总结
    ​一、两个基本需求无处不在的部署:无处不在很重要,如果系统的一小部分没有被监视,就会受到影响连续监测:因为通常情况下,不寻常或其他值得注意的系统行为很难或不可能重现最......