1.分布式链路追踪的起源
当周末躺在被窝里,点外卖时;双 11 的零点,疯狂提交订单时;假期和基友激情开黑,五杀超神…在这个精彩纷呈的互联网世界里,这些应用背后又隐藏着什么?每一次点击行为在 IT 世界里会流经哪些节点,调用哪些服务,带来哪些变化?这一切庞杂且精密,超出了人力探索的边界,而分布式链路追踪就是追溯请求在 IT 系统间流转路径与状态的一门技术。接下来,让我们通过对分布式链路追踪的来了解这个 IT 世界!
说到分布式链路追踪,就绕不开分布式系统与微服务的兴起。早期 IT 系统非常简单,几乎所有程序都运行在同一个节点,互相之间也没有什么依赖。但随着硬件技术突飞猛进,硬件成本大幅下降,软件复杂度却越来越高。单一系统性能无法满足复杂的数据计算任务,而软件逻辑的复杂性也导致维护成本大幅上升。另外,单节点的可靠性也难以保障,不可避免的会偶尔出现宕机等行为,影响软件的可用性。“性能、可维护性和可用性”这三大因素促使了分布式系统与微服务的诞生。
为了解决上述问题,人们很自然想到:既然一个硬件节点无法很好的运行软件,那能不能够通过多个节点来共同完成?并且为不同节点分派不同任务去提高效率。就好比通过不同角色分工协同的汽车生产流水线,分布式系统与微服务的理念亦是如此,如下图所示。
分布式系统与微服务自诞生就被广泛应用,主要得益于以下优势:
- 扩展性
分布式系统天然具备“按需扩展”的能力,比如双 11 大促前通过添加机器实现快速水平扩容,大促结束后释放机器,充分利用云计算的分时复用能力,节约成本。利用微服务,还可以实现按需精准扩容,比如登录服务扩容 10 倍,下单服务扩容3倍,最大化的节省资源。
- 可靠性
分布式系统可以有效抵抗“单点风险”,不会因为某一个节点的故障,影响整体的服务可用性。结合流量调度、离群实例摘除和弹性扩容等技术,甚至可以实现故障自愈。
- 可维护性
分布式系统可维护性更强,一方面我们将一个复杂服务拆分成多个简单的微服务,每个微服务的逻辑都更加清晰、更易理解。就好比我们写代码,将一个几百行的复杂函数重构成若干个简单函数,代码可读性就会直线上升。另一方面,一些通用的微服务可以被高度复用,无需重复开发和维护,比如你在开发一个电商 APP,可以直接调用第三方提供的支付、物流等服务接口,整体开发和维护效率将大幅提升。
虽然分布式系统与微服务具有非常显著优势,但凡事有利必有弊,它们在有效解决原有问题基础上,也为系统开发和运维带来了新挑战,主要包括以下几点:
- 模糊性
随着系统的分布式程度越来越高,异常表象与根因之间的逻辑联系变得愈加模糊,问题诊断的难度急剧上升。比如 A、B 两个服务共享同一个数据库实例,当 A 服务在压测期间,大量占用数据库的服务端连接和计算资源,会导致 B 服务出现连接超时或响应变慢等问题。如果 B 服务是通过 C 服务间接依赖该数据库实例,问题的定位就会变得更加困难。
- 不一致
虽然分布式应用从总体上变的更加可靠,但是每一个独立节点的状态却难以保证。导致这种不一致的原因有很多,比如前文提到的单机故障这种预期外的不一致,或者应用 Owner 执行分批发布或流量灰度时导致的预期内行为不一致。这种不一致性导致我们难以确定一个用户请求在系统内的准确执行路径与行为逻辑,可能引发不可预知的逻辑灾难。
- 去中心化
当你的系统拥有上千个微服务镜像运行在数百台机器实例上,你该如何梳理它们之间的依赖关系,又该如何找到核心业务的关键执行路径?特别是在分布式的场景下,你没有一个中心化的节点(Master)来保存每个服务之间的依赖与调度状态,每个独立节点都在自行其是,无法分辨自己在整个系统中的位置,只能“盲人摸象、管中窥豹”,缺乏全局视图。
分布式系统与微服务带来的新挑战无疑让人头痛,但也带来了新技术的发展契机,科技的发展总是这样循环往复,螺旋式上升。它们带来的新问题,促使了分布式链路追踪的诞生,使你能够有效的观察全局,追踪流量。我们将在下个章节了解分布式链路追踪的诞生历程与核心理念。
2.分布式链路追踪的诞生
为了应对分布式环境下的不一致、模糊性等前文提到的各类问题问题,人们试图通过请求粒度的轨迹追踪与数据透传,实现节点间的确定性关联,分布式链路追踪技术也由此诞生。
里程碑事件:Google Dapper
分布式链路追踪诞生的标志性事件就是 Google Dapper 论文的发表。2010 年 4 月,Benjamin H. Sigelman 等人在 Google Technical Report 上发表了《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,揭开了分布式链路追踪的技术大幕,开启了一段全新技术浪潮。
Dapper 首先明确了分布式链路追踪的两个目标:任意部署和持续监测。进而给出了三个具体的设计准则:
- 低开销:确保核心系统不会因为额外的性能开销拒绝使用。
- 应用级透明:对应用开发透明,无需开发人员的协助,降低接入门槛,提高迭代效率。
- 可扩展:在未来相当长一段时间内,随着业务的高速发展,仍然可以有效运转。
下面几张图展示了 Dapper 对链路透传、调用链结构和数据采集流程的描述,我们将在后续章节详细展开介绍,对 Dapper 感兴趣的同学建议直接阅读原作。
Dapper 论文有两个重要的意义,一是详细阐述了分布式链路追踪的设计理念,为后来的实现者提供了重要的理论指导;二是通过 Dapper 在 Google 生产环境的大规模落地实践,证明了分布式链路追踪技术的企业级价值,为分布式链路追踪的推广作出了不可磨灭的贡献。
基本原理
分布式链路追踪并不是无中生有、凭空诞生的新概念,而是轨迹追踪在 IT 领域的又一次成功运用。轨迹追踪理念早已被广泛应用于社会生活方方面面,比如物流订单追踪。一个快递包裹在发件站被赋予快递单号,沿途中转节点会记录该快递到达时间等信息,而用户通过快递单号就可以查询自己的包裹途径了哪些站点,耗时多久,是否存在滞留或丢件情况。下表对比了物流追踪与链路追踪的关联与差异性,以便大家理解。
分布式链路追踪的基本原理就是在分布式应用的接口方法上设置一些观察点(类似快递中转站记录点),然后在入口节点给每个请求分配一个全局唯一的标识 TraceId(类似快递单号),当请求流经这些观察点时就会记录一行对应的链路日志(包含链路唯一标识,接口名称,时间戳,主机信息等)。最后通过 TraceId 将一次请求的所有链路日志进行组装,就可以还原出该次请求的链路轨迹,如下图所示。
分布式链路追踪实现请求回溯的关键点有两个:一是低成本、高质量的观察点设置,也就是链路插桩,确保我们追踪的信息足够丰富,能够快速定位异常根因;二是保证链路上下文在不同环境下都能够完整透传,避免出现上下文丢失导致的断链现象。关于链路插桩和上下文透传的具体内容我们将在实战篇进行详细介绍。下面,我们来看一个高速公路例子,进一步加深对链路追踪实现原理的认识。
一辆汽车飞驰在高速公路上
小明、小红、小玉计划在“五一”期间去自驾游,他们的旅游路线各不相同。如果我们想追踪他们的行程轨迹与时间该如何实现?
可能你会建议在每辆车上安装一个追踪器。确实,这是一种行之有效的方法。但当出行车辆扩展到全国数以十亿计的规模,安装追踪器成本就会很高。此时我们换个角度思考,高速公路的路线是固定的,每隔一段距离就会有一个收费站,如果我们在每个收费站上安装监控,记录车辆在每个收费站的轨迹与时间,就可以很经济的实现车辆轨迹与行驶时间的追踪。最终,我们得到了如下行程记录:
如果我们将每个游客替换为服务请求,收费站替换为服务接口,那我们就可以得到每次请求在分布式系统中的调用轨迹与状态,这就是分布式链路追踪的含义。