基于 Tracing 数据的拓扑关系生成原理

背景

随着互联网架构的流行,越来越多的系统开始走向分布式化、微服务化。如何快速发现和定位分布式系统下的各类性能瓶颈成为了摆在开发者面前的难题。借助分布式追踪系统的调用链路还原能力,开发者可以完整地了解一次请求的执行过程和详细信息。但要真正分析出系统的性能瓶颈往往还需要链路拓扑、应用依赖分析等工具的支持。这些工具使用起来虽然简单,但其背后的原理是什么?本文将带您一起探索。

Jaeger 作为从 CNCF 毕业的第七个项目,已经成为了云原生架构下分布式追踪系统的第一选择。本文将以 Jaeger 为例,介绍基于 Tracing 数据的拓扑关系生成原理,文中使用的版本为1.14

Jaeger 架构

笔者曾在 2018 年初基于 Jaeger 1.2.0 做过一些开发,参见《开放分布式追踪(OpenTracing)入门与 Jaeger 实现》。经过十多个版本的发展,Jaeger 的架构发生了一些变化,目前在大规模生产环境中推荐下面 2 种部署模式。

Direct to storage

Collector 将采集到的 trace 数据直接写入 DB,Spark jobs 定期读取这些 trace 数据并将计算出的拓扑关系再次写入 DB 中。

Kafka as intermediate buffer

Collector 将采集到的 trace 数据写入中间缓冲区 Kafka 中,Ingerster 读取 Kafka 中的数据并持久化到 DB 里。同时,Flink jobs 持续读取 Kafka 中的数据并将计算出的拓扑关系写入 DB 中。

Jaeger 组件

一个完整的 Jaeger 系统由以下几部分组成。

  • Jaeger client libraries - 为不同语言实现了符合 OpenTracing 标准的 SDK。应用程序通过 API 写入数据,client library 把 trace 信息按照应用程序指定的采样策略传递给 jaeger-agent。
  • Agent - 它是一个监听在 UDP 端口上接收 span 数据的网络守护进程,它会将数据批量发送给 collector。它被设计成一个基础组件,部署到宿主机或容器里。Agent 将 client library 和 collector 解耦,为 client library 屏蔽了路由和发现 collector 的细节。
  • Collector - 接收 jaeger-agent 发送过来的 trace 数据,然后在处理管道中对它们进行验证、索引、转换并最终完成持久化存储。Jaeger 的存储组件被设计成可插拔的,目前官方支持 Cassandra、Elasticsearch 和 Kafka。
  • Query - 接收查询请求,然后从后端存储组件中检索 trace 并通过 UI 进行展示。
  • Ingester - 负责从 Kafka 中读取数据然后写入另一个存储后端。

拓扑关系生成

下图是 Jaeger 官方提供的微服务应用 Hot R.O.D. 的服务间拓扑关系。通过此图,开发者可以清楚地了解过去一段时间里服务间的调用关系和调用次数。

由于生产环境中的 trace 数据量巨大,每次查询时通过扫描数据库中的全量数据来构建拓扑关系不切实际。因此,Jaeger 提供了基于 Spark jobs 和 Flink jobs 两种从 trace 数据中提取拓扑关系的方法。

Jaeger Spark dependencies

Jaeger Spark dependencies 是一个 Spark 任务,它从特定的后端存储中读取 span 数据,计算服务间的拓扑关系,并将结果存储起来供 UI 展示。目前支持的后端存储类型有 Cassandra 和 Elasticsearch。 由于 Cassadra 和 Elasticsearch 计算拓扑关系的逻辑大同小异,下面将以 Elasticsearch 为例进行分析。

Span 数据组织结构

Jaeger 会根据 span 的 StartTime 字段将它们写到 Elasticsearch 以天为单位的 index 里,存放 span 的 index 组织结构如下:

jaeger-span-2019-11-11
jaeger-span-2019-11-12
jaeger-span-2019-11-13
...

拓扑关系计算流程

Spark job 每次运行都会重新计算指定日期的服务间拓扑关系,具体流程如下:

  1. 根据传入的日期定位存放 span 数据的 index,例如传入的日期是2019-11-11,则目标 span 为jaeger-span-2019-11-11。如果没有指定日期,便会使用当天的 index,此时 index 里存放着当天自午夜以来的所有 span 数据。
  2. 将目标 index 中的 span 数据按 traceID 进行分组,得到Map(traceID: Set(span))
  3. 针对单个 trace,遍历该 trace 的所有 span,计算出对应的拓扑关系List<dependency>
  4. Map(traceID: List<dependency>)按 dependency 重新分组,并累加相同 dependency 之间的调用次数。
  5. 将计算结果写入 Elasticsearch 用于存放拓扑关系的 index 里。例如jaeger-span-2019-11-11对应的拓扑关系 index 为jaeger-dependencies-2019-11-11

拓扑关系查询

查询时会根据传入的 lookback 查询对应时间段的 dependency 数据,默认为过去 24 小时。查询过程很简单:

  1. 找出和指定时间范围有交集的所有 dependency index。
  2. 从这些 index 中过滤出符合要求的所有 dependency。
  3. 将 dependency 在 UI 层进行聚合展示。

Jaeger Analytics

Jaeger Analytics 是一个 Flink 任务,它从 Kafka 中消费 span 数据,实时计算服务间的拓扑关系,最后将计算结果写入 Cassadra 中。

拓扑关系计算流程

将 Kafka 设为 source

这里将 Kafka 设置为 Flink 任务的 source,此时 span 数据将不断地从 Kafka 流向 Flink 任务。

将离散的 span 聚合成 trace

DataStream<Iterable<Span>> traces = spans.filter((FilterFunction<Span>) span -> span.isClient() || span.isServer()).name(FILTER_LOCAL_SPANS).keyBy((KeySelector<Span, String>) span -> String.format("%d:%d", span.getTraceIdHigh(), span.getTraceIdLow())).window(EventTimeSessionWindows.withGap(Time.minutes(3))).apply(new SpanToTraceWindowFunction()).name(SPANS_TO_TRACES).map(new AdjusterFunction<>()).name(DEDUPE_SPAN_IDS).map(new CountSpansAndLogLargeTraceIdFunction()).name(COUNT_SPANS);
  1. filter((FilterFunction<Span>) span -> span.isClient() || span.isServer())只保留有 client 或 server 标签的 span。
  2. keyBy((KeySelector<Span, String>) span -> String.format("%d:%d", span.getTraceIdHigh(), span.getTraceIdLow())) - 基于 traceIdHigh 和 traceIdLow 的组合将 span 数据分组。
  3. window(EventTimeSessionWindows.withGap(Time.minutes(3))) - 为每个 trace 创建一个 gap 为 3 分钟的会话窗口。表示对于某个 trace,如果 3 分钟内没有新的 span 数据到达,就认为窗口结束,进而触发后续的聚合操作。
  4. SpanToTraceWindowFunction - 负责将会话窗口里的 span 数据收集到一起。
  5. AdjusterFunction负责去除一个 trace 里的重复 span。
  6. CountSpansAndLogLargeTraceIdFunction以 10 秒为单位,统计 span 数量随时间的分布。

计算 dependencies

DataStream<Dependency> dependencies = traces.flatMap(new TraceToDependencies()).name(TRACE_TO_DEPENDENCIES).keyBy(key -> key.getParent() + key.getChild()).timeWindow(Time.minutes(30)).sum("callCount").name(PREAGGREGATE_DEPENDENCIES);
  1. flatMap(new TraceToDependencies()) - 遍历一个 trace 的所有 span 数据,收集该 trace 表征的拓扑关系。
  2. keyBy(key -> key.getParent() + key.getChild()) - 将具有相同父子关系的 dependency 分到一组。
  3. timeWindow(Time.minutes(30)).sum("callCount") - 为每对依赖关系创建一个 30 分钟的时间窗口,窗口结束触发计数操作。

将 Cassandra 设为 sink

这里将 Cassandra 设置为 Flink 任务的 sink,当依赖关系因满足时间窗口的触发条件被计算完毕后,将以dependencies(ts, ts_index, dependencies)的形式持久化到 Cassandra 中。

拓扑关系查询

根据指定的时间范围过滤出所有符合要求的 dependency,然后在 UI 层进行聚合展示。从 Cassandra 查询 dependency 使用的 CQL 如下。

SELECT ts, dependencies FROM dependencies WHERE ts_index >= startTs AND ts_index < endTs

总结

Spark jobs、Flink jobs 两种计算拓扑关系的方案虽然在细节上有所不同,但整体流程非常相似,可总结成下图。

对于 Jaeger Spark dependencies, 拓扑关系的精确程度和 Spark job 的执行频率密切相关。执行频率越高,查询结果越精确,但消耗的计算资源也会越多。举个例子,如果 Spark job 每小时运行一次,拓扑关系可能无法反映最近一小时服务间的调用情况。

对于 Jaeger Analytics,它以 Kafka 作为缓存,增量地处理到达的 span 数据,具有更好的实时性。如果对最近时间拓扑关系的精确程度有比较高的要求,建议选用 Jaeger Analytics 方案。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/517390.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一条命令导出MySQL表结构xls

文章目录&#x1f331;介绍&#x1f337;一、先尝鲜&#x1f498;二、导出失败的看过来&#x1f412;三、原理&#x1f437;总结&#x1f331;介绍 &#x1f337;一、先尝鲜 &#x1f343;执行下面SQL语句&#xff0c;将会发生神奇的事情&#x1f601; SELECT 字段名称,数据…

揭秘2019双11背后的云网络 – 双11网络架构和洛神系统

图1 天猫双11成交额 2019年天猫双11成交额&#xff0c;2684亿&#xff01;核心系统100%上云&#xff01;全球最大流量洪峰&#xff0c;阿里云扛住了。 狂欢背后的技术栈 网上轻松购物体验实际上是背后复杂的技术组成的&#xff0c;这是一个简化的通用电商系统架构&#xff0…

拿专属内推码!一汽-大众专场直播招聘来了

作者 | 张红月出品 | CSDN遇见OFFER开学即毕业毕业即失业线下宣讲招聘统统被按下了暂停键迷茫&#xff0c;焦虑&#xff0c;惶恐而HR却说&#xff0c;今年招人太难了腾讯总监甚至路边摆摊招聘2020年各大企业纷纷开启线上模式CSDN作为深受开发者喜爱的社区以用户为本特开设遇见O…

vmware workstation 12 打开vm18 不兼容问题解决

由于需要让别人给我发了一下xp系统的虚拟机&#xff0c;可是打开后&#xff0c;却显示&#xff1a;配置文件“”是由VMware产品创建&#xff0c;但该产品与此版VMware workstations 不兼容&#xff0c;因此无法使用。 解决方案&#xff1a; 分析&#xff1a; 出现这种情况主要…

阿里云开源 image-syncer 工具,容器镜像迁移同步的终极利器

为什么要做这个工具&#xff1f; 由于阿里云上的容器服务 ACK 在使用成本、运维成本、方便性、长期稳定性上大大超过公司自建自维护 Kubernets 集群&#xff0c;有不少公司纷纷想把之前自己维护 Kubernetes 负载迁移到阿里云 ACK 服务上。在迁移过程中&#xff0c;往往会碰到一…

短网址系统设计与实战

&#x1f3a8;领域&#xff1a;Java后端开发&#x1f525;收录专栏&#xff1a; 系统设计与实战 &#x1f412;个人主页&#xff1a;BreezAm &#x1f496;Gitee&#xff1a;https://gitee.com/BreezAm ✨个人标签&#xff1a;【后端】【大数据】【前端】【运维】 文章目录&am…

“我,懂数据,不怕被裁”:这项核心能力到底有多香?

我见过市面上很多的 Python 讲解教程和书籍&#xff0c;他们大都这样讲 Python 的&#xff1a;先从 Python 的发展历史开始&#xff0c;介绍 Python 的基本语法规则&#xff0c;Python 的 list, dict, tuple 等数据结构&#xff0c;然后再介绍字符串处理和正则表达式&#xff0…

RuoYi-Cloud 登陆 /code 获取验证码出错

文章目录1. 异常信息2. 分析定位3. 解决方案1. 异常信息 [网关异常处理]请求路径:/code,异常信息:Invalid value ‘KaptchaTextCreator’ for config parameter ‘kaptcha.textproducer.impl’. 2. 分析定位 如果不修改包名的话&#xff0c;默认不会出现此问题&#xff0c;…

谁顶住双11的世界级流量洪峰?神龙架构负责人等9位大牛现场拆解阿里秘籍

阿里江湖中&#xff0c;很多资源和技术&#xff0c;如神龙服务器、OceanBase、POLARDB等等&#xff0c;在开源、自研、云这三架马车上形成协同效应&#xff0c;既是内功也是武器。 “不是任何一朵云都能撑住这个流量。中国有两朵云&#xff0c;一朵是阿里云&#xff0c;一朵叫…

如何回答性能优化的问题,才能打动阿里面试官?

阿里妹导读&#xff1a;日常工作中&#xff0c;我们多少都会遇到应用的性能问题。在阿里面试中&#xff0c;性能优化也是常被问到的题目&#xff0c;用来考察是否有实际的线上问题处理经验。面对这类问题&#xff0c;阿里工程师齐光给出了详细流程。来阿里面试前&#xff0c;先…

RuoYi-Cloud [网关异常处理]请求路径:/code,异常信息:null

文章目录1. 现象2. 分析定位3. 解决方案1. 现象 nacos配置文件中有值&#xff0c;但是代码初始化时未赋上值 2. 分析定位 既然nacos已经配置了&#xff0c;获取不到只能存在二种情况&#xff0c; 第一种&#xff1a;获取的不是最新的nacos的配置 第二种&#xff1a;没有…

这 10 行比较字符串相等的代码给我整懵了,不信你也来看看

来源 | 程序猿石头责编 | Carol 封图 | CSDN 下载自视觉中国先直接上代码&#xff1a;boolean safeEqual(String a, String b) {if (a.length() ! b.length()) {return false;}int equal 0;for (int i 0; i < a.length(); i) {equal | a.charAt(i) ^ b.charAt(i);}return …

SpringBoot整合websocket实现及时通信聊天

&#x1f3a8;领域&#xff1a;Java后端开发&#x1f525;收录专栏&#xff1a; 系统设计与实战 &#x1f412;个人主页&#xff1a;BreezAm &#x1f496;Gitee&#xff1a;https://gitee.com/BreezAm ✨个人标签&#xff1a;【后端】【大数据】【前端】【运维】 文章目录&am…

2019双11,支付宝有哪些“秘密武器”?

2019双11&#xff0c;支付宝参战的第十一年。 与十一年前相比&#xff0c;双11的许多东西都改变了。比如金额——2684亿&#xff0c;差不多是十一年前的5000倍&#xff1b;比如流量——订单峰值54.4万笔/秒&#xff0c;曾经是想都不敢想的数字&#xff1b;再比如层出不穷的新技…

一文看懂 K8s 日志系统设计和实践

导读&#xff1a;上一篇文章《6 个 K8s 日志系统建设中的典型问题&#xff0c;你遇到过几个&#xff1f;》中我们介绍了为什么需要一个日志系统、为什么云原生下的日志系统如此重要以及云原生背景下日志系统的建设难点&#xff0c;相信 DevOps、SRE、运维等同学看了之后深有体会…

如何在 Kubernetes 上配置 Jenkins?

作者 | Sudip Sengupta译者 | 火火酱&#xff0c;责编 | Carol封图 | CSDN 下载自视觉中国在本文中&#xff0c;我们将一起完成在Kubernetes上配置Jenkins的工作。作为一款被广泛使用的开源CI服务器&#xff0c;Jenkins提供了数百个插件&#xff0c;能够为我们项目的构建、部署…

MySQL做数据统计SQL语句整理大全(原理+实战)

&#x1f3a8;领域&#xff1a;Java后端开发&#x1f525;收录专栏&#xff1a; MySQL原理与实战 &#x1f412;个人主页&#xff1a;BreezAm &#x1f496;Gitee&#xff1a;https://gitee.com/BreezAm ✨个人标签&#xff1a;【后端】【大数据】【前端】【运维】 文章目录&a…

如何在一周内上线50个用户增长策略

在闲鱼用户增长业务上的实验 我们最先落地的业务是在用户增长上&#xff0c;闲鱼的用户增长业务有如下描述&#xff1a; 闲鱼的卖家都是普通小卖家&#xff0c;而非专业的B类商家。因此无法统一组织起来参加营销活动带来买家活跃。我们目前DAU已经突破到2000W&#xff0c;如何…

jstat gc各参数含义

参数说明S0C第一个幸存区的大小S1C第二个幸存区的大小S0U第一个幸存区的使用大小S1U第二个幸存区的使用大小EC伊甸园区的大小EU伊甸园区的使用大小OC老年代大小OU老年代使用大小MC方法区大小MU方法区使用大小CCSC压缩类空间大小CCSU压缩类空间使用大小YGC年轻代垃圾回收次数YGC…

MySQL用户如何构建实时数仓

依托数据库生态&#xff0c;AnalyticDB for MySQL可以给用户提供分析场景下的标准解决方案&#xff0c;尤其是在大数据和性能要求较高的情况下AnalyticDB for MySQL的价值可以更好的体现。 MySQL用户为什么要单独构建数据仓库 为什么要单独构建数据仓库&#xff0c;而不是直接…