分布式追踪:我们都做错了

笔记。 翻译。:本材料的作者是 Cindy Sridharan,他是 imgix 的一名工程师,专门从事 API 开发,特别是微服务测试。 在这份材料中,她分享了她对分布式追踪领域当前问题的详细看法,她认为,该领域缺乏真正有效的工具来解决紧迫的问题。

分布式追踪:我们都做错了
[插图取自 其他材料 关于分布式追踪。]

据认为, 分布式追踪 实施难度和回报 充其量是可疑的。 跟踪出现问题的原因有很多,通常是因为配置每个系统组件以随每个请求传输适当的标头所涉及的工作量。 虽然这个问题确实存在,但绝不是无法克服的。 顺便说一句,它并不能解释为什么开发人员并不真正喜欢跟踪(即使它已经在运行)。

分布式追踪的主要挑战不是收集数据、标准化分发和呈现结果的格式,或者确定采样的时间、地点和方式。 我并没有试图去想象 琐碎的 事实上,这些“可理解性问题”是相当重要的技术问题,并且(如果我们考虑真正的开源) 标准和协议)需要克服的政治挑战才能认为这些问题已得到解决。

然而,如果我们想象所有这些问题都得到解决,那么很可能什么都不会发生重大变化 最终用户体验。 在最常见的调试场景中,跟踪可能仍然没有实际用途——即使在部署之后也是如此。

如此不同的痕迹

分布式跟踪包括几个不同的组件:

  • 为应用程序和中间件配备控制工具;
  • 分布式上下文传输;
  • 痕迹收集;
  • 痕迹存储;
  • 它们的提取和可视化。

许多关于分布式跟踪的讨论倾向于将其视为一种一元操作,其唯一目的是帮助全面诊断系统。 这很大程度上是由于分布式追踪的想法在历史上是如何形成的。 在 博客条目,在 Zipkin 源码打开时制作,其中提到 它 [Zipkin] 让 Twitter 更快。 第一个用于追踪的商业产品也被宣传为 APM工具.

笔记。 翻译。:为了使进一步的文本更容易理解,让我们根据以下定义两个基本术语: OpenTracing 项目文档:

  • 跨度 ——分布式追踪的基本要素。 它是对某个工作流程(例如数据库查询)的描述,包括名称、开始和结束时间、标签、日志和上下文。
  • Span 通常包含到其他 Span 的链接,允许将多个 Span 组合成 追踪 — 请求在分布式系统中移动时的生命周期的可视化。

跟踪包含非常有价值的数据,可以帮助完成生产测试、灾难恢复测试、错误注入测试等任务。 事实上,一些公司已经将跟踪用于类似的目的。 让我们从 通用上下文迁移 除了简单地将跨度移动到存储系统之外,还有其他用途:

  • 例如,优步 使用 跟踪结果以区分测试流量和生产流量。
  • Facebook 使用 跟踪数据以进行关键路径分析以及定期灾难恢复测试期间的流量切换。
  • 还有社交网络 适用 Jupyter 笔记本允许开发人员对跟踪结果运行任意查询。
  • 附着物 低密度脂蛋白 (谱系驱动的故障注入) 用于通过错误注入进行测试的分布式跟踪。

上面列出的选项都不完全适用于该场景 调试,在此期间工程师尝试通过查看迹线来解决问题。

当谈到 到达调试脚本,主界面还是图 跟踪视图 (虽然有些人也称其为 “甘特图” или 《瀑布图》)。 在下面 跟踪视图 я 我是说 共同构成跟踪的所有跨度和随附元数据。 每个开源跟踪系统以及每个商业跟踪解决方案都提供了 跟踪视图 用于可视化、详细说明和过滤痕迹的用户界面。

到目前为止我见过的所有跟踪系统的问题是,所产生的 可视化(跟踪视图) 几乎完全反映了迹线生成过程的特征。 即使提出了替代可视化:热图、服务拓扑、延迟直方图,它们最终仍然归结为 跟踪视图.

过去我 抱怨 UI/UX 跟踪中的大多数“创新”似乎仅限于 开启 跟踪中的附加元数据,以高基数投资于它们的信息 (高基数) 或提供深入到特定范围或运行查询的能力 迹线间和迹线内。 在这种情况下, 跟踪视图 仍然是主要的可视化工具。 只要这种情况继续下去,分布式跟踪(最好的情况下)将在调试工具中排名第四,仅次于指标、日志和堆栈跟踪,最坏的情况下,它会浪费金钱和时间。

跟踪视图的问题

命运 跟踪视图 — 提供单个请求在与其相关的分布式系统的所有组件之间移动的完整情况。 一些更高级的跟踪系统允许您深入了解各个跨度并查看一段时间内的细分情况 一个进程(当跨度具有功能边界时)。

微服务架构的基本前提是组织结构随着公司需求而增长的思想。 微服务的支持者认为,将各种业务任务分配到各个服务中可以让小型自主开发团队控制此类服务的整个生命周期,从而使他们能够独立构建、测试和部署这些服务。 然而,这种分布的缺点是丢失了有关每个服务如何与其他服务交互的信息。 在这种情况下,分布式追踪声称是不可或缺的工具 调试 服务之间复杂的交互。

如果你真的 极其复杂的分布式系统,那么没有人能够把它记在脑子里 充分 图片。 事实上,基于假设甚至可能的假设来开发工具是一种反模式(一种无效且低效的方法)。 理想情况下,调试需要一个可以帮助的工具 缩小您的搜索范围,以便工程师可以专注于与正在考虑的问题场景相关的维度子集(服务/用户/主机等)。 在确定故障原因时,工程师不需要了解故障期间发生了什么 一次性提供所有服务,因为这样的要求与微服务架构的理念相矛盾。

然而,traceview 是 准确 这。 是的,当跟踪中的跨度数量太大而无法在一个可视化中显示时,某些跟踪系统会提供压缩跟踪视图。 然而,由于即使在如此精简的可视化中也包含大量信息,工程师仍然 被迫 “筛选”它,手动将选择范围缩小到一组成为问题根源的服务。 不幸的是,在这个领域,机器比人类快得多,更不容易出错,而且结果更可重复。

我认为 Traceview 错误的另一个原因是它不利于假设驱动的调试。 调试的核心是 迭代的 从假设开始,然后沿着不同向量验证从系统中获得的各种观察结果和事实、结论/概括并进一步评估假设的真实性的过程。

机会 又快又便宜 检验假设并相应地改进心理模型是 基石 调试任何调试工具都应该 交互的 并缩小搜索空间,或者在出现错误线索的情况下,允许用户返回并专注于系统的不同区域。 完美的工具可以做到这一点 主动地,立即引起用户对潜在问题区域的注意。

唉, 跟踪视图 不能称为具有交互界面的工具。 使用它时您所能期望的最好的结果就是找到延迟增加的一些来源,并查看与其关联的所有可能的标签和日志。 这无助于工程师识别 模式 流量,例如延迟分布的细节,或检测不同测量之间的相关性。 广义迹线分析 可能有助于解决其中一些问题。 真的吗, 有例子 使用机器学习进行成功分析,以识别异常跨度并识别可能与异常行为相关的标签子集。 然而,我还没有看到令人信服的机器学习或数据挖掘结果可视化应用于与跟踪视图或 DAG(有向无环图)显着不同的跨度。

跨度级别太低

Traceview 的根本问题是 跨度 对于延迟分析和根本原因分析来说,这些原语都太低级了。 这就像解析单个处理器命令以尝试解决异常一样,知道有更高级的工具(例如回溯)使用起来更方便。

此外,我将冒昧地声明以下内容:理想情况下,我们不需要 完整的图片 发生在请求生命周期期间,由现代跟踪工具表示。 相反,需要某种形式的更高级别的抽象,其中包含有关什么的信息 出错了 (类似于回溯),以及一些上下文。 与其观看整个轨迹,我更喜欢看到它 часть,发生有趣或不寻常的事情。 目前,搜索是手动进行的:工程师接收轨迹并独立分析跨度以搜索有趣的东西。 人们盯着各个跟踪中的跨度以希望检测可疑活动的方法根本无法扩展(特别是当他们必须理解不同跨度中编码的所有元数据时,例如跨度 ID、RPC 方法名称、跨度持续时间) 'a、日志、标签等)。

跟踪视图的替代方案

当跟踪结果能够以一种可视化的方式提供对系统互连部分中发生的情况的重要洞察时,跟踪结果是最有用的。 在此之前,调试过程很大程度上仍然存在 惰性的 并且取决于用户注意到正确的相关性、检查系统的正确部分或将拼图的各个部分放在一起的能力 - 与 工具,帮助用户制定这些假设。

我不是视觉设计师或用户体验专家,但在下一节中我想分享一些关于这些可视化效果的想法。

专注于特定服务

在这个行业正在围绕想法进行整合的时候 SLO(服务水平目标)和SLI(服务水平指标),各个团队应该优先考虑确保他们的服务与这些目标保持一致似乎是合理的。 它遵循 服务导向 可视化最适合此类团队。

跟踪(尤其是没有采样的跟踪)是有关分布式系统每个组件的信息宝库。 这些信息可以输入到一个狡猾的处理器中,该处理器将为用户提供服务 服务导向 结果。它们可以提前识别 - 甚至在用户查看痕迹之前:

  1. 仅针对高度突出的请求的延迟分布图 (异常值请求);
  2. 未实现服务SLO目标时的延迟分布图;
  3. 最常出现的查询中最“一般”、“有趣”和“奇怪”的标签 被重复;
  4. 延迟细分情况 根据 服务未实现其 SLO 目标;
  5. 各种下游服务的延迟细分。

其中一些问题根本无法通过内置指标来回答,迫使用户仔细检查跨度。 结果,我们有一个对用户极其敌对的机制。

这就提出了一个问题:不同团队控制的不同服务之间的复杂交互如何? 不是吗 跟踪视图 不被认为是突出这种情况的最合适的工具吗?

移动开发人员、无状态服务的所有者、托管有状态服务(如数据库)的所有者和平台所有者可能对其他东西感兴趣 推介会 分布式系统; 跟踪视图 对于这些根本不同的需求来说,这个解决方案太通用了。 即使在非常复杂的微服务架构中,服务所有者也不需要对超过两三个上下游服务有深入的了解。 本质上,在大多数场景下,用户只需要回答以下问题: 有限的服务.

这就像为了仔细检查而通过放大镜查看一小部分服务。 这将允许用户就这些服务及其直接依赖关系之间的复杂交互提出更紧迫的问题。 这类似于服务世界中的回溯,工程师知道 错了,对周边服务发生的事情也有一定了解才能理解 为什么.

我所推广的方法与自上而下、基于跟踪视图的方法完全相反,在该方法中,分析从整个跟踪开始,然后逐渐深入到各个范围。 相比之下,自下而上的方法首先分析靠近事件潜在原因的小区域,然后根据需要扩大搜索空间(有可能引入其他团队来分析更广泛的服务)。 第二种方法更适合快速检验初始假设。 一旦获得具体结果,就可以进行更有针对性和更详细的分析。

构建拓扑

如果用户知道,特定于服务的视图会非常有用 什么 一个服务或一组服务会增加延迟或导致错误。 然而,在复杂的系统中,在故障期间识别有问题的服务可能是一项不简单的任务,特别是在服务没有报告错误消息的情况下。

构建服务拓扑对于确定哪个服务正在经历错误率峰值或延迟增加从而导致服务显着降级有很大帮助。 当我谈论构建拓扑时,我的意思并不是 服务地图,显示系统中可用的每项服务并以其 死星形状的建筑地图。 该视图并不比基于有向无环图的跟踪视图更好。 相反我想看到 动态生成服务拓扑,基于某些属性,例如错误率、响应时间或任何用户定义的参数,有助于澄清特定可疑服务的情况。

让我们举个例子。 让我们想象一个假设的新闻网站。 主页服务 (首页) 与 Redis 交换数据,包括推荐服务、广告服务和视频服务。 视频服务从 S3 获取视频并从 DynamoDB 获取元数据。 推荐服务从 DynamoDB 接收元数据,从 Redis 和 MySQL 加载数据,并将消息写入 Kafka。 广告服务从 MySQL 接收数据并将消息写入 Kafka。

下面是该拓扑的示意图(许多商业路由程序都构建了该拓扑)。 如果您需要了解服务依赖性,它会很有用。 然而,期间 调试,当某个服务(例如视频服务)表现出响应时间增加时,这种拓扑不是很有用。

分布式追踪:我们都做错了
假设的新闻网站的服务图

下图会更合适。 服务有问题 (视频) 描绘在正中心。 用户立即注意到它。 从该可视化中可以清楚地看出,由于 S3 响应时间增加,视频服务工作异常,影响了部分主页的加载速度。

分布式追踪:我们都做错了
动态拓扑仅显示“有趣”的服务

动态生成的拓扑比静态服务映射更有效,尤其是在弹性、自动扩展的基础设施中。 比较和对比服务拓扑的能力允许用户提出更相关的问题。 关于系统的更精确的问题更有可能导致更好地理解系统如何工作。

对比展示

另一种有用的可视化是比较显示。 目前迹线不太适合并排比较,因此比较通常是 跨度。 而这篇文章的主要思想恰恰是span太低级,无法从trace结果中提取最有价值的信息。

比较两条轨迹并不需要全新的可视化。 事实上,像直方图这样表示与跟踪视图相同的信息就足够了。 令人惊讶的是,即使是这种简单的方法也比简单地分别研究两条痕迹带来更多的成果。 甚至更强大的可能性 形象化 痕迹比较 总共。 了解最近部署的数据库配置更改以启用 GC(垃圾收集)如何影响下游服务的几个小时的响应时间将非常有用。 如果我在这里描述的听起来像是对基础设施变化影响的 A/B 分析 在许多服务中 使用跟踪结果,那么您离事实就不远了。

结论

我不质疑追踪本身的用处。 我真诚地相信,没有其他方法可以像跟踪中所包含的那样收集如此丰富、因果性和上下文相关的数据。 然而,我也相信所有跟踪解决方案使用这些数据的效率都非常低。 只要跟踪工具仍然停留在跟踪视图表示上,它们充分利用可从跟踪中包含的数据中提取的有价值信息的能力就会受到限制。 此外,还存在进一步开发完全不友好且不直观的可视化界面的风险,这将严重限制用户排除应用程序中的错误的能力。

即使使用最新的工具,调试复杂的系统也非常困难。 工具应该帮助开发人员制定和测试假设, 积极提供 相关信息,识别异常值并注意延迟分布的特征。 为了使跟踪成为开发人员在排除生产故障或解决跨多个服务的问题时的首选工具,需要与创建和运营这些服务的开发人员的心智模型更加一致的原始用户界面和可视化。

设计一个系统需要花费大量的精力,以一种易于分析和推理的优化方式来表示跟踪结果中可用的各种信号。 您需要考虑如何在调试期间抽象系统拓扑,以帮助用户克服盲点,而无需查看单独的迹线或跨度。

我们需要良好的抽象和分层能力(尤其是在 UI 中)。 非常适合假设驱动的调试过程,您可以在其中迭代地提出问题并测试假设。 它们不会自动解决所有可观察性问题,但它们会帮助用户增强直觉并提出更聪明的问题。 我呼吁采取更加深思熟虑和创新的可视化方法。 这里确实有拓展视野的前景。

译者PS

另请阅读我们的博客:

来源: habr.com

添加评论