前言现代微服务系统中,一套复杂的分布式 Web 系统中,客户端的一次请求操作,可能需要经过系统中多个模块、多个中间件、多台机器的相互协作才能完成,并且这一系列调用请求中,有些是串行处理的,有些是并发执行的,那么如何确定客户端的一次操作背后调用了哪些应用、哪些模块,经过了哪些节点,每个模块的调用先后顺序是怎样的,每个模块的性能问题如何?随着业务系统模型的日趋复杂化,分布式系统中急需一套链路追踪(Trace)系统来解决这些痛点。
分布式服务跟踪是整个分布式系统中跟踪一个用户请求的过程,包括数据采集、数据传输、数据存储、数据分析和数据可视化,捕获此类跟踪让我们构建用户交互背后的整个调用链的视图,这是调试和监控微服务的关键工具。
Google Dapper 就是这样需求下的一套应用于大型分布式系统环境下的链路追踪系统。借助 Dapper 理念,系统开发人员只需将 Trace 组件嵌入到基础通用库中,就可以正常运行,而应用层开发者则不需要关心具体 Trace 组件实现、集成方式,达到以应用层透明的方式嵌入各个模块的目的。
Google Dapper 简介Google Dapper 这一分布式跟踪系统,最初只是作为一个自给自足的监控工具起步的,但最终进化成一个监控平台,并且促生出多种多样的甚至已经不是由 Dapper 团队开发的监控工具,说明分布式追踪系统在当前的分布式环境下是必不可少的工具。
现代互联网服务通常实现为复杂的大规模系统,比如采用流行的微服务架构模式。应用是由一组服务组合起来的,这些服务可能是由不同的团队开发的,而且可能采用不同的编程语言。像 Google 这种级别的公司,应用会跨越多个基础设施的上千台机器,即便是相对较小的云计算用例,推荐的做法也是使用跨地域的 Availability Zone 和 Region 运行服务的多个版本。在这种复杂的系统环境中,分布式追踪系统能够辅助我们理解系统的行为、帮助调试和排查性能问题。
Google 最初开发 Dapper 为了收集更多的复杂分布式系统的行为信息,然后呈现给 Google 的开发者们。这样的分布式系统因那些大规模的低端服务器作为互联网服务的载体,是一个特殊的经济划算的平台。想要在这个上下文中理解分布式系统的行为,就需要监控那些横跨了不同的应用、不同的服务器之间的关联动作。
从众多的分布式系统应用中得出的经验,对于分布式追踪系统需要满足至少两点要求:涵盖面的广度和持续的监控。涵盖广度的重要性不言而喻,因为在使用追踪系统的进行监控时,如果有一小部分没被监控到,那么人们对这个系统是不是值得信任都会产生巨大的质疑。另外,监控应该是 7x24 小时的,毕竟,系统异常或是那些重要的系统行为有可能出现过一次,就很难甚至不太可能重现。那么,根据这两个明确的需求,可以推出如下几个具体的设计目标:
- 低性能损耗 (Low overhead):分布式在线系统对于性能、资源要求都很严格,Trace 组件必须对服务影响足够小。对于一些高度优化过的服务,即使一点点性能损耗也会很容易察觉到,而且有可能迫使在线服务的部署团队不得不将分布式追踪系统关停。
- 应用级的透明 (Application-level transparency):应用层开发者不需要对 Trace 组件关心,Trace 嵌入到基础通用库中,提供高稳定性,而如果 Trace 需要应用开发者配合,那可能会引入额外的 bug 导致 Trace 系统更加脆弱。面对当下互联网公司快速迭代的开发环境来说,这一点尤其重要。
- 扩展性 (Scalability):Google 的服务在线集群数量可想而知,一次检索就可能跨越上百台甚至成千台机器,因此这个 Trace Infrastructure 的扩展性也很重要。
当然,以上几点设计目标的背后,还有一个额外的设计目标就是追踪数据产生之后,能够快速导出数据,快速进行数据分析,在最短的时间内定位系统异常,理想情况是数据存入跟踪仓库后一分钟内就能统计出来。尽管跟踪系统对一小时前的旧数据进行统计也是相当有价值的,但如果跟踪系统能提供足够快的信息反馈,就可以对生产环境下的异常状况做出快速反应。
另外,要做到真正的应用级别的透明(这应该是当下面临的最挑战性的设计目标),我们需要把核心跟踪代码做的很轻巧,然后把它植入到那些无所不在的公共组件中,比如线程调用、控制流以及 RPC 库。使用自适应的采样率可以使跟踪系统变得可伸缩,并降低性能损耗。结果展示的相关系统也需要包含一些用来收集跟踪数据的代码,用来图形化的工具,以及用来分析大规模跟踪数据的库和 API。虽然单独使用 Dapper 有时就足够让开发人员查明异常的来源,但是 Dapper 的初衷不是要取代所有其他监控的工具。Dapper 的数据往往侧重性能方面的调查,其他监控工具也有他们各自的用处。 |