关闭

微服务架构下,如何实现分布式跟踪?

733人阅读 评论(0) 收藏 举报
分类:

http://www.infoq.com/cn/articles/how-to-realize-distributed-tracking?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk

前段时间,我们有发布过一篇题为《类似Google Dapper,微服务需要这样的分布式跟踪工具》的文章,很多读者反馈没看尽兴,确实,文章只是谈到分布式追踪工具的意义,以及可以解决什么问题,但并没有谈到如何实现分布式追踪。今天这篇文章,作者是东软集团基础软件事业部技术总监,他在这方面有丰富的经验,文中他将会聊到目前主流的几个解决方案实现思路以及他们的落地方案。


随着互联网技术的高速发展,各种创新技术、前沿概念如雨后春笋般层出不穷,云服务、云计算、大数据处理、大数据分析……,以往单应用的服务架构已经很难处理如山洪般增长的信息数据,随着分布式的普及、服务的快速增长与云计算技术的进步,微服务架构逐渐进入人们的实现,它也因其特有的优势而备受关注。

微服务架构的本质,是把整体的业务拆分成很多有特定明确功能的服务,通过很多分散的小服务之间的配合,去解决更大,更复杂的问题。对被拆分后的服务进行分类和管理,彼此之间使用统一的接口来进行交互。

微服务的特点决定了功能模块的部署是分布式的,以往在单应用环境下,所有的业务都在同一个服务器上,如果服务器出现错误和异常,我们只要盯住一个点,就可以快速定位和处理问题,但是在微服务的架构下,大部分功能模块都是单独部署运行的,彼此通过总线交互,都是无状态的服务,这种架构下,前后台的业务流会经过很多个微服务的处理和传递,我们难免会遇到这样的问题:

  • 分散在各个服务器上的日志怎么处理?
  • 如果业务流出现了错误和异常,如何定位是哪个点出的问题?
  • 如何快速定位问题?
  • 如何跟踪业务流的处理顺序和结果?

我们发现,以前在单应用下的日志监控很简单,在微服务架构下却成为了一个大问题,如果无法跟踪业务流,无法定位问题,我们将耗费大量的时间来查找和定位问题,在复杂的微服务交互关系中,我们就会非常被动。

对于这个问题,业内已经有了一些实践和解决方案,让我们来看看行业内的领先设计思想。

Google Dapper

Google公司广泛使用了分布式集群,为了应对自身大规模的复杂集群环境,Google公司研发了Dapper分布式跟踪系统,并发表了论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,给行业内分布式跟踪的实现提供了非常有价值的参考,该论文也成为了当前分布式跟踪系统的理论基础。

我们先来看个例子:

图1 这个路径由用户的X请求发起,穿过一个简单的服务系统。用字母标识的节点代表分布式系统中的不同处理过程。

分布式服务的跟踪系统需要记录在一次特定的请求中系统中完成的所有工作的信息。举个例子,上图展现的是一个与5台服务器相关的一个服务,包括:前端(A),两个中间层(B和C),以及两个后端(D和E)。当一个用户(这个用例的发起人)发起一个请求时,首先到达前端,然后发送两个RPC调用到服务器B和C。B会马上做出反应,但是C需要和后端的D和E交互之后再返还给A,由A来响应最初的请求。对于这样一个请求,简单实用的分布式跟踪的实现,就是为服务器上每一次发送和接收动作来收集跟踪标识符(message identifiers)和时间戳(timestamped events)。

基于这个模型,Google在此论文中提出了几个重要的概念:

1、基于标注(annotation-based),又叫植入点或埋点

在应用程序或中间件中明确定义一个全局的标注(annotation),它可以是一个特殊的ID,通过这个ID连接每一条记录和发起者的请求,当然,这需要代码植入,在生产环境中,因为所有的应用程序都使用相同的线程模型,控制流和RPC系统,可以把代码植入限制在一个很小的通用组件库中,从而达到监测系统应用对开发人员的透明。Dapper能够以对应用开发者近乎零侵入的成本对分布式控制路径进行跟踪,几乎完全依赖于少量通用组件库的改造。

  • 当一个线程在处理跟踪控制路径的过程中,Dapper把这次跟踪的上下文在ThreadLocal中进行存储。追踪上下文是一个小而且容易复制的容器,其中承载了Scan的属性比如跟踪ID和span ID。

  • 当计算过程是延迟调用的或是异步的,大多数Google开发者通过线程池或其他执行器,使用一个通用的控制流库来回调。Dapper确保所有这样的回调可以存储这次跟踪的上下文,而当回调函数被触发时,这次跟踪的上下文会与适当的线程关联。在这种方式下,Dapper可以使用trace ID和span ID来辅助构建异步调用的路径。

  • Google几乎所有的进程间通信都是建立在一个用C++和Java开发的RPC框架上。我们通过跟踪植入该框架来定义RPC中所有的span。span的ID和跟踪的ID会从客户端发送到服务端。基于RPC的系统被广泛使用在Google中,这是一个重要的植入点。

2、跟踪树和span

图2:5个span在Dapper跟踪树中的关联关系

在Dapper跟踪树结构中,树节点是整个架构的基本单元,而每一个节点又是对span的引用。节点之间的连线表示的span和它的父span的直接关系。通过简单的parentId和spanId就可以有序地把所有的关系串联起来,达到记录业务流的作用。

Twitter公司的Zipkin

Twitter公司的Zipkin是Google Dapper系统的开源实现,Zipkin严格按照Dapper论文实现,采用Scala编写,并且紧密集成到Twitter公司自己的分布式服务Finagle中,使得跟踪做到对应用透明。

图3:Zipkin应用架构图

Zipkin的整体架构如上图所示,涵盖了信息的收集、处理和展现。

淘宝鹰眼系统(EagleEye)

淘宝鹰眼是基于网络调用日志的分布式跟踪系统,它可以分析网络请求在各个分布式系统之间的调用情况,从而得到处理请求的调用链上的入口URL、应用服务的调用关系,从而找到请求处理瓶颈,定位错误异常的根源位置。同时,业务方也可以在调用链上添加自己的业务埋点日志,使各个系统的网络调用与实际业务内容得到关联。

图4:鹰眼系统的总体架构图

我们的解决方案

针对于微服务,东软平台产品提供了一套完整的微服务解决方案,在此基础上,对微服务架构进行了扩展,基于Google Dapper的概念,设计了一套基于微服务架构的分布式跟踪系统。

该跟踪系统支持基于dubbo的微服务框架的监控,以及分布式服务调用链跟踪:

图5:东软UniEAP平台基于微服务的分布式跟踪系统流程设计图

分布式跟踪系统的整体流程是通过扩展dubbo作为入口,把监控代码植入到dubbo-filter扩展模块中,然后通过trace-client模块抓取日志数据,存入文件服务器,为了避免产生大量Trace对象造成内存堆积引发的GC问题,trace首先采取写入堆外内存的方式落地,然后通过trace-agent代理模块读取日志信息,给trace-collector收集模块提供日志数据,trace-collector收集模块通过提供统一的接口,为外部获取数据提供支持,可以传输到数据库记录,或者传输给其他的数据分析产品。Trace-web模块作为可视化展示平台,展现服务的完整跟踪链条、心跳监控信息、dubbo原生监控信息,达到数据的展示工作。

除了数据的跟踪以外,该系统还会整合数据分析功能:

图6:集成数据分析功能,提升数据的利用价值

通过集成可视化分析产品,简单的分布式跟踪功能变成了可视化的监控系统,跟踪中产生的数据,会发挥出更大的价值:

 

  1. 实时抓取数据,实时分析统计,生成统计和报表

  2. 可视化的报表系统,更快的了解系统运行状态

  3. 搜索功能,快速的定位关键问题

  4. 数据挖据,利用优秀的数据分析能力和数据模型,进行数据预测

  5. 分布式跟踪系统应用展望

在分布式场景越来越普及的今天,分布式跟踪将作为微服务必备的基础组件存在,完善的跟踪系统可以极大的提高开发和运维的效率,是企业应用发展不可获缺的组成部分,特别是以下几点:

1、业务流调用流程跟踪

分布式系统的所有日志信息可以通过完善的跟踪串联起来,使系统的运维更加稳定,定位问题更加准确。

2、可视化的监控界面

通过分布式跟踪系统的可视化监控页面,避免了去服务器上查看日志的烦恼。

3、业务分析

在使用了分布式跟踪系统后,我们可以快速的梳理每个调用链路,分析耗时过长的业务是如何产生的,并且可以定位性能不佳的调用片段,合理的分析问题,为性能优化提供非常有价值的参考意见。

作者简介

张德阳,东软集团基础软件事业部技术总监,具有十多年基础平台软件的开发、架构和实施经验,目前主要关注微服务、DevOps、数据分析等领域。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:222139次
    • 积分:3104
    • 等级:
    • 排名:第11138名
    • 原创:46篇
    • 转载:390篇
    • 译文:0篇
    • 评论:5条
    最新评论