普元推出DevOps系列课程,5分钟秒懂一个知识点,戳“阅读原文”充电5分钟,掌握黑科技。
转载本文需注明出处:微信公众号EAWorld,违者必究。
随着分布式服务架构的流行,特别是微服务等设计理念在系统中的应用,系统规模也会变得越来越大,各微服务间的调用关系也变得越来越复杂。通常一个由客户端发起的请求在后端系统中会经过多个不同的微服务调用来协同产生最后的请求结果。
在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路。那么就带来一系列问题,在业务规模不断增大、服务不断增多以及频繁变更的情况下,如何快速发现问题?如何判断故障影响范围?如何梳理服务依赖以及依赖的合理性?如何分析链路性能问题以及实时容量规划?面对上面这些问题,Spring Cloud Sleuth提供了分布式服务跟踪解决方案。
目录:
一、为什么需要以及什么是分布式服务跟踪系统
二、分布式服务跟踪:SpringCloudSleuth
三、分布式服务跟踪系统其他解决方案
一、为什么需要以及什么是
分布式服务跟踪系统
为什么需要分布式服务跟踪系统
随着分布式服务架构的流行,特别是微服务等设计理念在系统中的应用,业务的调用链越来越复杂。
可以看到,随着业务的发展,系统规模也会变得越来越大,各微服务间的调用关系也变得越来越复杂。通常一个由客户端发起的请求在后端系统中会经过多个不同的微服务调用来协同产生最后的请求结果,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路,在每条链路中任何一个依赖服务出现延迟过高或者错误都有可能引起请求最后的失败。同时,缺乏一个自上而下全局的调用id,如何有效的进行相关的数据分析工作?对于大型网站系统,如淘宝、京东等电商网站,这些问题尤其突出。
什么是分布式服务跟踪系统
分布式服务跟踪是整个分布式系统中跟踪一个用户请求的过程(包括数据采集、数据传输、数据存储、数据分析、数据可视化),捕获此类跟踪让我们构建用户交互背后的整个调用链的视图,这是调试和监控微服务的关键工具。Spring Cloud Sleuth是Spring Cloud为分布式服务跟踪提供的解决方案,有了它,我们可以:
提供链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。
可视化各个阶段耗时,进行性能分析
各个调用环节的可用性、梳理服务依赖关系以及优化
数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。
下面我们来看一个典型的分布式系统请求调用过程,如下图所示:
分布式服务跟踪系统的设计
分布式服务跟踪系统设计目标
低入侵性,应用透明:即作为也业务组件,应当尽可能少入侵或者无入侵其他业务系统,对于使用方透明,减少开发人员的负担。
低损耗:服务调用埋点本身会带来性能损耗,这就需要调用跟踪的低损耗,实际中还会通过配置采样率的方式,选择一部分请求去分析请求路径。
大范围部署,扩展性:作为分布式系统的组件之一,一个优秀的调用跟踪系统必须支持分布式部署,具备良好的可扩展性。
埋点与生成日志
埋点即系统在当前节点的上下文信息,可以分为客户端埋点、服务端埋点,以及客户端和服务端双向型埋点。埋点日志通常要包含以下内容traceId、spanId、调用的开始时间,协议类型、调用方ip和端口,请求的服务名、调用耗时,调用结果,异常信息等,同时预留可扩展字段,为下一步扩展做准备;
收集和存储日志(主要支持分布式日志采集的方案,同时增加MQ作为缓冲)
分析和统计调用链路数据,以及时效性
展现以及决策支持
二、分布式服务跟踪:
SpringCloudSleuth
快速入门
在引入Sleuth之前,我们需要做一些准备工作,具体如下所示:
服务注册中心(eureka-server)
微服务应用分别为trace1和trace2(它们都有一个REST接口,其中trace1通过RestTemplate调用trace2的REST接口)
微服务应用trace1和trace2项目基本一样(除配置端口、应用名称和REST的Path),以trace1为示例:
pom.xml文件增加依赖(如下所示)
主要代码:
配置文件
运行结果,日志没有没有跟踪信息
我们在浏览器或者postman通过http://localhost:8080/trace1,可以返回trace2相应接口的内容,同时我们看到控制台并没有跟踪信息打印,微服务应用trace1和trace2的日志信息具体如下图所示:
添加跟踪依赖 ,日志信息存在跟踪信息
如何为上面的trace1和trace2添加服务跟踪功能呢?SpringCloudSleuth对于此进行封装,使得我们为应用增加服务跟踪能力的操作非常简单,满足前面所说设计目标(低入侵,应用透明),只需在trace1和trace2的pom.xml依赖管理中增加Spring-cloud-starter-sleuth依赖即可,具体如下所示:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
添加sleuth依赖后,分别重启trace1和trace2,再次通过浏览器或者postman调用http://localhost:8080/trace1,可以返回trace2相应接口的内容,同时我们看到控制台日志已经存在跟踪信息,微服务应用trace1和trace2的日志信息具体如下图所示:
从上面的控制台输出内容中,我们看到多出了一些形如[trace1,454445a6a7d9ea44,912a7c66c17214e0,false]的日志信息,而这些元素正是实现分布式服务跟踪的重要组成部分,它们的含义分别如下所示:
第一个值:trace1,它表示应用的名称,也就是配置文件spring.application.name的值。
第二个值:454445a6a7d9ea44,它是SpringCloudSleuth生成的一个ID,称为Trace ID,它用来标识一条请求链路,一条请求链路中包含一个Trace ID,多个Span ID。
第三个值:912a7c66c17214e0,它是SpringCloudSleuth生成的另外一个ID,称为Span ID,它表示一个基本的工作单元,比如发送一个http请求。
第四个值:false,表示是否要将该信息输出到Zipkin等服务中来收集和展示。
上面四个值中的Trace ID 和Span ID是SpringCloudSleuth实现分布式服务跟踪的核心。在一次服务请求链路的调用过程中,会保持并传递同一个Trace ID,从而将整个分布于不同微服务进程中的请求跟踪信息串联起来。例如,在一次前端请求链路中,上面trace1和trace2的Trace ID是相同的。
跟踪原理
分布式服务跟踪系统主要包括下面三个关键点:
(1)Trace:它是由一组有相同Trace ID的Span串联形成一个树状结构。为了实现请求跟踪,当请求请求到分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的跟踪标识(即前文提到的Trace ID),同时在分布式系统内部流转的时候,框架始终保持传递该唯一标识,直到返回请求为止,我们通过它将所有请求过程中的日志关联起来;
(2)Span:它代表了一个基础的工作单元,例如服务调用。为了统计各处理单元的时间延迟,当前请求到达各个服务组件时,也通过一个唯一标识(即前文提到的Span ID)来标记它的开始、具体过程以及结束。通过span的开始和结束的时间戳,就能统计该span的时间延迟,除此之外,我们还可以获取如事件名称、请求信息等元数据。
(3)Annotation:它用于记录一段时间内的事件。内部使用的最重要的注释是:
cs (Client Send):客户端发出请求,为开始跨度
sr (Server Received):服务器已收到请求并开始处理。timestampsr - timestampcs =网络延迟。
ss (Server Send):服务器处理完毕准备发送到客户端。timestampss - timestampsr =服务器上的请求处理时间。
cr (Client Received):客户端接收到服务器响应,为跨度结束。客户端已成功接收到服务器的响应。timestampcr - timestampcs =请求的总时间。
以下是在使用Sleuth的两个微服务之间的调用中请求的行为方式,除了生成唯一标识符并将其添加到应用程序日志之外,还需要在作为请求的一部分的微服务器之间正确传播它们。
抽样收集
我们在对接分析系统时就会碰到一个问题:分析系统在收集跟踪信息的时候,需要收集多少跟踪信息才合适呢?生产环境与开发环境跟踪信息收集比例应该不一致,我们是否可以调整呢?同时,不同业务系统收集比例可能也不一样。
理论上来说,我们收集的跟踪信息越多就可以越好反映出系统的实际运行情况,并给出更精确的预警和分析。但在高并发的分布式系统运行时,大量的请求调用会产生海量的跟踪日志信息,如果收集过多的跟踪信息将会对整个分布式系统的性能造成一定的影响,同时保存大量的日志信息也需要不少的存储开销。所以,在Sleuth中采用了抽象收集的方式来跟踪信息打上标记,也就是我们前面第四个布尔值,它代表了该信息是否要被后续的跟踪信息收集器获取和存储。
默认情况下,Sleuth会使用PercentageBasedSampler实现的抽样策略,以请求百分比的方式配置和收集跟踪信息,默认值0.1(代表收集10%的请求跟踪信息),可以通过配置spring.sleuth.sampler来修改收集的百分比。
与ELK整合
前面随着已经有了跟踪信息,但是由于日志文件都分布在各个服务实例的文件系统上,如果链路上服务比较多,查看日志文件定位问题是一件非常麻烦的事情,所以我们需要一些工具来帮忙集中收集、存储和搜素这些跟踪信息。引入基于日志的分析系统是一个不错的选择,比如ELK平台,SpringCloudSleuth在与ELK平台整合使用时,实际上只需要与负责日志收集的Logstash完成数据对接即可,所以我们需要为logstash准备Json格式的日志输出(SpringBoot应用默认使用logback来记录日志,而logstash自身也有对logback日志工具支持)。与ELK整合架构图如下所示:
与Zipkin整合
虽然通过ELK平台提供的收集、存储、搜索等强大功能,但是缺少对请求链路中各阶段时间延迟的关注,而很多时候我们追溯请求链路的一个原因是为了找出整个链路中出现延迟过高的瓶颈源,或者找出问题服务实例等监控与时间消耗相关的需求,ELK就显得乏力,反而引入Zipkin就能够轻松解决。
Zipkin是Twitter的一个开源项目,它基于Google Dapper实现。我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的Rest API接口来辅助查询跟踪数据以分布式系统的监控程序,通过UI组件帮助我们及时发现系统中出现的延迟升高问题以及系统性能瓶颈根源。下面展示Zipkin的基础架构,它主要由4个核心组件构成:
Collector(收集器组件):主要负责收集外部系统跟踪信息,转化为Zipkin内部的Span格式。
Storage(存储组件):主要负责收到的跟踪信息的存储,默认为内存,同时支持存储到Mysql、Cassandra以及Elasticsearch。
Restful API(API组件):提供接口,方便外部系统进行集成。
Web UI(展示组件):基于API开发的自带展示界面,方便进行跟踪信息的查看以及查询,同时进行相关的分析。
与zipkin整合——HTTP收集
sleuth收集跟踪信息通过http请求发送给zipkin server,zipkinserver进行跟踪信息的存储以及提供Rest API即可,Zipkin UI调用其API接口进行数据展示。其大体路流程如下图所示:
代码如何实现呢?主要有两个部分:搭建Zipkin Server、为应用引入zipkin依赖和配置,具体如下所示:
(1)搭建Zipkin Server
添加Pom依赖
主要代码
配置文件
(2)为应用引入zipkin依赖和配置
添加Pom依赖
为应用增加配置文件
启动Zipkin Server以及分别重启trace1和trace2,再次通过浏览器或者postman调用http://localhost:8080/trace1,可以返回trace2相应接口的内容,同时我们看到控制台日志已经存在跟踪信息,然后通过浏览器访问http://localhost:9411/,我们可以看到Zipkin对于跟踪信息分析与展示,可以看到请求链路,以及每个span的具体耗时,就能分析进行链路优化、依赖分析等操作,其界面具体如下所示:
与zipkin整合——消息中间件收集
Spring Cloud Sleuth在整合Zipkin时,不仅实现了以Http的方式收集,还实现了通过消息中间件来对跟踪信息进行异步收集。通过结合Spring Cloud Stream,我们可以非常轻松地让应用客户端将跟踪信息输出到消息中间件,同时Zipkin服务端从消息中间件上异步获取这些跟踪信息,具体如下所示:
代码如何实现呢?主要有两个部分:搭建Zipkin Server、为应用引入zipkin依赖和配置,具体如下所示:
(1)搭建Zipkin Server
添加Pom依赖
主要代码(使用注解@EnableZipkinStreamServer)
配置文件
(2)为应用引入zipkin依赖和配置
添加Pom依赖
为应用增加配置文件
与Zipkin整合——数据存储
默认情况下,Zipkin Server会将跟踪信息存储在内存中,但是这样就会出现我们重启Zipkin Server时之前收集的跟踪信息丢失的问题。为了解决此问题,Zipkin提供了多种存储方式,比如Mysql、Cassandra以及Elasticsearch,以Mysql为例,我们能够很轻松地为Zipkin Server增加Mysql存储功能。主要有三个步骤即可:第一步,在Mysql中创建数据库并且运行其数据脚本;第二步,为pom添加数据库依赖;第三步,修改配置更换存储方式。更多内容请我另一篇博客《微服务之分布式跟踪系统(springboot+zipkin)》。
(博客地址:http://blog.csdn.net/qq_21387171/article/details/53787019)
与Zipkin整合——API接口
Zipkin不仅提供了Web UI方便用户进行跟踪信息查看与查询,同时还提供了Rest API,方便第三方系统进行集成进行跟踪信息的展示和监控,其提供的API列表如下所示:
三、分布式服务跟踪系统其他解决方案
OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。 OpenTracing提供了用于运营支撑系统的和针对特定平台的辅助程序库。下面为其相应的成员以及提供的产品:
分布式服务跟踪系统其他解决方案:Jaeger
Jaeger(https://github.com/jaegertracing/jaeger)受到Dapper和Zipkin的启发,从开始就建立了OpenTracing支持,是由Uber Technologies作为开源发布的分布式跟踪系统。它可用于监控基于微服务的体系结构:分布式上下文传播、分布式事务监控、根本原因分析、服务依赖性分析以及性能/延迟优化。其架构图如下所示:
分布式服务跟踪系统其他解决方案: Sky Walking
Skywalking (https://github.com/wu-sheng/sky-walking)全链路监控开源项目,也是唯一的国内团队开源的APM监控项目。其架构图如下所示:
最后,附上文章所讲内容的源码下载地址(源码地址:https://github.com/dreamerkr/SpringCloudSleuthExample.git ),需要可以进行下载与交流。
关于作者:
王召
现任普元信息资深开发工程师,为普元新一代数字化企业云平台开发团队一员,负责新一代SPM(软件产品管理)与MKT(软件市场)领域系统的开发。曾在百度西北营销自主研发中心、格林谈谈科技等互联网公司从事开发经理工作,曾主导开发过多款电商和社交项目,并获得风险基金的投资。平时喜欢旅游,骑行,爬山等活动。
关于EAWorld
微服务,DevOps,元数据,企业架构原创技术分享,EAii(Enterprise Architecture Innovation Institute)企业架构创新研究院旗下官方微信公众号。
微信号:eaworld,长按二维码关注
普元推出DevOps系列课程,5分钟秒懂一个知识点,戳“阅读原文”充电5分钟,掌握黑科技↓↓↓
阅读原文:http://mp.weixin.qq.com/s?timestamp=1506676654&src=3&ver=1&signature=NtQH4jkkXQHZr2DwB5ZVfRf0Wctr0V2zZLC6se43qy8yM1hL*fW6PBQnwwljQgijPuvoFpLt28foJktADY*ENeCdoqQBx*ldMlpKGWSri2rz3tFC9BL7RAL2DbFSq1kAt6vMZngB*yrFRAOB1XfPFVLxoH*yHPnjKQtKlym5hc0=&devicetype=Windows-QQBrowser&version=61030004&pass_ticket=qMx7ntinAtmqhVn+C23mCuwc9ZRyUp20kIusGgbFLi0=&uin=MTc1MDA1NjU1&ascene=1