可观测性作为系统高可用的重要保障,已经成为系统建设中不可或缺的一部分。但随着业务逻辑越来越复杂,传统的ELK方案在日志采集、筛选、分析等方面更加费时费力,而分布式会话追踪方案在追踪能力的基础上改进了日志的串联,但侧重于更多在调用链上也很难直接应用于高效的业务跟踪。一、背景1、业务系统日趋复杂随着互联网产品的快速发展,不断变化的业务环境和用户需求带来了复杂的业务需求。业务系统需要支持越来越多的业务场景,覆盖越来越多的业务逻辑,系统的复杂度也在快速增加。同时,由于微服务架构的演进,业务逻辑的实现往往需要依赖多个服务之间的协作。总而言之,业务系统越来越复杂已经成为一种常态。2、业务跟踪面临挑战业务系统经常面临各种日常客户投诉和突发问题,“业务跟踪”成为关键的应对手段。业务跟踪可以看作是业务执行的现场还原过程。通过执行过程中的各种记录可以还原出原站点,用于分析业务逻辑的执行情况,定位问题。是整个系统建设的重要组成部分。目前在分布式场景下,业务追踪的主流实现方式有两种,一种是基于日志的ELK方案,一种是基于单次请求调用的会话追踪方案。但是,随着业务逻辑的日益复杂,上述方案越来越不适合当前的业务系统。1)传统的ELK解决方案日志是业务系统必不可少的能力。它的职责是记录程序运行过程中发生的离散事件,并在事后阶段分析程序的行为,比如调用了哪些方法,操作了哪些数据等。在分布式系统中,ELK技术栈已经成为日志采集和分析的通用方案。如下图1所示,随着业务逻辑的执行,业务日志会被打印、收集并存储在Elasticsearch(以下简称ES)中。图1业务系统ELK案例传统的ELK方案需要开发者在写代码的时候尽可能完整地打印日志,然后通过关键字段从ES中收集过滤与业务逻辑相关的日志数据,进而拼凑出业务执行信息的场景.但该方案存在以下痛点:日志采集繁琐:ES虽然提供了日志检索能力,但日志数据往往缺乏结构化的文本片段,难以快速完整地采集所有相关日志。日志筛选难:不同业务场景和业务逻辑之间存在重叠,重叠逻辑打印出的业务日志可能会相互干扰,难以筛选出正确的关联日志。耗时的日志分析:采集的日志只是零散的数据,只能读取代码,结合逻辑,人工逐条分析日志,尽可能还原现场。综上所述,随着业务逻辑和系统复杂度的增加,传统的ELK方案在日志采集、日志筛选、日志分析等方面越来越费时费力,业务难以快速追踪。2)分布式会话跟踪方案在分布式系统中,尤其是微服务系统中,业务场景中的某个请求往往需要经过多个服务、多个中间件、多台机器的复杂链接来处理。为了解决复杂环节排查难的问题,“分布式会话跟踪解决方案”应运而生。该方案的理论知识由谷歌在2010年的《Dapper》论文发表,随后推特开发了Zipkin的开源版本。市面上几乎所有的同类型框架都是基于GoogleDapper论文实现的。整体类似,都是通过一个分布式的全局唯一id(traceId)连接同一个请求分布在各个服务节点上。修复通话关系,跟踪系统问题,分析通话数据,统计系统指标。分布式会话跟踪是一种会话级跟踪能力。如下图2所示,将单个分布式请求还原为一个调用链路,从客户端发起请求开始,到达系统边界,记录请求流经的每一个会话。服务直到响应返回给客户端。图2一个典型请求的全过程(来自《Dapper》)分布式会话跟踪的主要作用是分析分布式系统的调用行为,不能很好地应用于业务逻辑跟踪。下图3是一个审计业务场景的跟踪案例。业务系统提供外部审计能力,对审计对象的审计需要经过“初审”和“审核”两个环节(两个环节关联同一个taskId)。因此,整个审核流程调用了两次审核接口的执行。如图左侧所示,完整的审计场景涉及很多“业务逻辑”的执行,而分布式会话跟踪只是根据两次RPC调用在右侧生成两个调用链接,无法准确描述审计场景业务逻辑的执行,问题主要体现在以下几个方面:图3分布式会话跟踪案例无法同时跟踪多个调用链路分布式会话跟踪只支持单个请求的调用跟踪,当业务场景包含多个调用,会生成多个调用链接;由于调用链路通过traceId串联,不同链路之间相互独立,增加了完整业务追踪的难度。例如在排查审计场景下的业务问题时,由于初审和复审是不同的RPC请求,不可能同时直接获取两个调用链接,通常需要额外存储两个traceId映射关系.无法准确描述业务逻辑全景分布式会话跟踪生成的调用链接只包含单个请求的实际调用,一些未执行的调用和本地逻辑无法在链接中体现,导致无法准确描述完整业务逻辑视图。例如,对于同一个评论界面,最初的评论链接1包含服务b的调用,而评论链接2则没有。这是因为review场景中存在“判断逻辑”,而这个逻辑是无法在调用环节中体现出来的。还是需要手动结合代码进行分析。无法专注于当前业务系统的逻辑执行。分布式会话跟踪涵盖单个请求流经的所有服务、组件、机器等。它不仅包括当前的业务系统,还涉及到很多下游的服务。当接口内部逻辑复杂时,调用环节的深度和复杂度会大幅增加,业务跟踪其实只需要关注当前业务系统的逻辑执行即可。比如review场景产生的调用链接,涉及很多下游服务的内部调用,给当前业务系统的排查增加了复杂度。3)总结传统的ELK解决方案是一种滞后的业务跟踪。之后需要从大量离散的日志中收集过滤出需要的日志,并手动对日志进行序列化分析。这个过程必然是费时费力的。分布式会话跟踪方案是在调用执行过程中实时完成链接的动态拼接,但由于是会话层面的,只关注调用关系等问题,无法很好地应用于业务跟踪。因此,无论是传统的ELK方案还是分布式会话追踪方案都无法满足日益复杂的业务追踪需求。本文希望实现一个以业务逻辑跟踪为核心的高效解决方案,以业务链路为载体高效组织拼接业务执行日志,支持业务执行现场还原和可视化查看,从而提高定位问题的效率,即可视化全链接日志跟踪。下面将介绍可视化全链路日志跟踪的设计思路和总体方案,并介绍新方案在大众点评内容平台上的实现,旨在帮助有类似业务系统开发需求的同学提供一些思路。二、可视化全链路日志跟踪1、设计思路可视化全链路日志跟踪是在前期考虑的,即在业务执行的同时实现业务日志的高效组织和动态连接,如图下图4。这时候离散的Log数据会按照业务逻辑进行组织,绘制执行现场,从而实现高效的业务跟踪。图4业务系统日志跟踪案例新的解决方案需要回答两个关键问题:如何高效组织业务日志,以及如何动态连接业务日志。下面将一一解答。1)如何高效整理业务日志?为了实现高效的业务跟踪,首先需要准确完整地描述业务逻辑,形成业务逻辑全景图,而业务跟踪实际上就是通过执行过程中的日志数据,还原全景图中业务执行的场景。新的解决方案抽象了业务逻辑并定义了业务逻辑链接。下面以“回顾业务场景”为例,说明业务逻辑环节的抽象过程:逻辑节点,可以是本地方法(如图5“判断逻辑”节点)或RPC等远程调用方法(如图5“逻辑A”节点)。逻辑链路:业务系统对外支持很多业务场景,每个业务场景对应一个完整的业务流程,可以抽象为由逻辑节点组成的逻辑链路。下图5中的逻辑链接准确、完整准确地描述了“审计业务场景”。业务踪迹是逻辑链路某次执行的还原。逻辑链路完整准确地描述了业务逻辑全景图,并作为载体实现业务日志的高效组织。图5业务逻辑链接案例2)如何动态序列化业务日志?业务逻辑执行过程中的日志数据原本是离散存储的,但此时需要实现的是将各个逻辑节点的日志与业务逻辑的执行动态关联起来,进而还原出完整的业务逻辑执行现场。由于逻辑节点与逻辑节点之间经常通过MQ或RPC进行交互,新方案可以利用分布式会话跟踪提供的分布式参数透传能力,实现业务日志的动态级联:通过不断执行的线程和网络通信透传参数来实现在执行业务逻辑的同时不间断传输链路和节点标识,实现离散日志的着色。基于识别,染色的离散日志将动态串联到正在执行的节点上,逐渐汇聚成完整的逻辑链路,最终实现业务执行现场的高效组织和可视化展示。与分布式会话跟踪方案不同,当多个分布式调用同时串联时,新方案需要结合业务逻辑选择一个公共id作为标识。例如,图5中的审计场景涉及2个RPC调用。确保2个执行串联到同一个逻辑链接。此时结合审计业务场景,选取与初审、复审相同的“任务id”作为标识,彻底实现审计场景的逻辑链连接,进行现场还原。2.总体方案在明确了日志的高效组织和动态串联两个基本问题后,本文选取图4业务系统中的“逻辑环节1”对总体方案进行详细描述。该方案可以拆解为以下几个步骤:图46通用方案的拆解1)链路定义“链路定义”是指:用特定的语言静态描述一个完整的逻辑链路。一条链路通常由多个逻辑节点按照一定的业务规则组成。规则是逻辑节点之间的执行关系,包括串行、并行和条件分支。DSL(DomainSpecificLanguage)是专门为解决某一类任务而设计的计算机语言。它可以通过JSON或XML定义一系列节点(逻辑节点)的组合关系(业务规则)。因此,本方案选择使用DSL来描述逻辑链路,实现从抽象定义到具体实现的逻辑链路。图7链接的抽象定义和具体实现逻辑链接1-DSL[{"nodeName":"A","nodeType":"rpc"},{"nodeName":"Fork","nodeType":"fork","forkNodes":[[{"nodeName":"B","nodeType":"rpc"}],[{"nodeName":"C","nodeType":"local"}]]},{"nodeName":"加入","nodeType":"加入","joinOnList":["B","C"]},{"nodeName":"D","nodeType":"decision","decisionCases":{"true":[{"nodeName":"E","nodeType":"rpc"}]},"defaultCase":[{"nodeName":"F","nodeType":"rpc"}]}]2)链路染色“链路染色”是指:在链路执行过程中,通过透传和串口识别,明确哪个链路正在执行,哪个节点已经执行。链接染色包括两个步骤:①第一步:确定序列标识,当逻辑链接打开时,确定唯一标识,可以明确后续要执行的链接和节点。链接唯一标识=业务标识+场景标识+执行标识(三个标识共同决定“某业务场景某某执行”)业务标识:赋予链接业务意义,如“用户id”、“活动id”等场景ID:给出链接场景的含义,例如当前场景为“逻辑链接1”。ExecutionID:赋予链接执行意义。例如,如果只涉及单次调用,则可以直接选择“traceId”;如果涉及多个调用,则根据业务逻辑为多个调用选择相同的“publicid”。节点唯一标识=链路唯一标识+节点名称(这两个标识共同决定了“某个业务场景下某个执行中的一个逻辑节点”)节点名称:DSL中预设的节点的唯一名称,如“A”.②Step2调用系列标识。逻辑链接执行时,系列标识在分布式完整链接中透传,动态系列链接中的执行节点实现链接的着色。例如“逻辑链路1”中:当“A”节点触发执行后,开始在后续链路和节点中传输序列标识,并随着业务流程的执行逐步完成整个链路的着色.当标识符传递给“E”节点时,表示“D”条件分支的判断结果为“真”,同时将“E”节点动态串联到执行的链路上.3)链接上报“链接上报”的意思是:在链接执行过程中,以链接组织的形式上报日志,实现对业务站点的准确保存。图8链路上报示意图如上图8所示,上报的日志数据包括:节点日志和业务日志。节点日志的作用是绘制链路中执行过的节点,记录节点的开始、结束、输入、输出;业务日志的作用是展示链路节点具体业务逻辑的执行情况,记录对业务逻辑的影响。可解释的数据,包括与上下游交互的输入输出参数、复杂逻辑的中间变量、逻辑执行抛出的异常。4)链路存储“链路存储”的含义是:将链路执行过程中上报的日志存储在地面上,用于后续的“现场修复”。上报的日志分为链路日志、节点日志、业务日志三种类型:元信息、链接起止时间等节点日志:在一次链接执行中,执行节点的基本信息,包括节点名称、节点状态、节点起止时间等业务日志:在一个链路单次执行,执行节点中的业务日志信息,包括日志级别、日志时间、日志数据等。下图是链路存储的存储模型,包括链路日志、节点日志、服务日志、以及linkmetadata(配置数据),是一个如下图9所示的树状结构,其中以服务标识为根节点。用于后续链接查询。图9链接的树状存储结构III.大众点评内容平台实践1.业务特点与挑战互联网时代,内容为王。内容平台的核心策略是构建内容管道,确保内容持续、健康、有价值地流向内容消费者,最终形成内容“生产→治理→消费→生产”的良性循环。大众点评、美团App内容丰富多样,站内外商家及合作伙伴消费场景众多。对于内容流水线中的三方,有如下要求:内容生产者:希望生产的内容能够在更多的渠道传播,获得更多的流量,受到消费者的喜爱。内容治理方:希望作为“防火墙”过滤掉合法合规的内容,同时融合机器和人的能力,丰富内容属性。内容消费者:希望获得满足其个性化需求的内容,吸引其种草,或协助其做出消费决策。生产者有不同的内容模型,需要不同的处理方式,消费者对内容也有个性化的要求。如果每个生产者和消费者分别连接,内容模型异构、处理过程和输出门槛不同等问题会带来连接成本高、效率低的问题。在此背景下,点评内容平台应运而生。作为内容管道的“总督”,实现了内容的统一接入、统一处理、统一输出:图10统一接入点评内容平台业务形态:统一内容数据模型,对接不同内容生产者,转化异构内容转化为内容平台的通用数据模型。统一处理:统一处理能力建设,积累和提升通用机器处理和人工操作能力,确保内容合法合规,属性丰富。统一输出:统一输出门槛构建,对接不同内容消费者,为下游提供符合个性化需求的标准化内容数据。如下图11所示,是点评内容平台的核心业务流程。每一条内容都会经过这个过程,最后决定是否在各个频道下发布。图11内容平台业务流程点评内容平台是否及时准确处理内容是内容生产者和消费者关注的核心问题,也是日常值班客户投诉的主要类型。内容平台的业务追踪建设主要面临以下难点和复杂性:业务场景多:业务流程涉及多个不同的业务场景,不同的逻辑,如实时接入、人工操作、分布重算等。部分场景上市。逻辑节点多:业务场景涉及逻辑节点多,不同的内容类型有不同的节点。例如,在同一个实时接入场景下,笔记内容和直播内容执行的逻辑节点有很大差异。多次触发执行:业务场景会被多次触发,因来源不同逻辑也会不同。例如,笔记内容经过作者编辑、系统审核等,会触发实时访问场景的重新执行。评论内容平台每天处理数百万条内容,涉及数百万个业务场景的执行,逻辑节点的执行高达上亿个。业务日志分散在不同的应用中,不同内容、不同场景、不同节点和多个第一次执行的日志混合在一起。无论是日志收集还是现场恢复,都相当繁琐和耗时。传统的业务跟踪解决方案越来越不适合内容平台。评论内容平台迫切需要新的解决方案来实现高效的业务追踪,因此我们进行了可视化全链路日志追踪的建设。下面的文章将介绍相关实践和成果。2.实践与成果1)实践复习内容平台是一个复杂的业务系统,对外支持多种业务场景。通过对业务场景的梳理和抽象,可以定义实时接入、人工操作、任务导入、分发重计算等多个业务逻辑环节。由于点评内容平台涉及到很多内部服务和下游依赖服务,每天支撑着大量的内容处理服务,随着业务的执行会产生大量的日志数据。同时,链路上报也需要修改很多服务。因此,点评内容平台在通用的全链路日志追踪方案的基础上,进行了以下具体实践。①支持大容量日志的上报和存储点评内容平台实现了图12所示的日志上报架构,支持对众多业务进行统一的日志采集、处理和存储,可以很好地支持大规模下日志追踪的建设数据。图12评论内容平台日志上报架构日志采集:各应用服务通过本机部署的log_agent采集异步上报的日志数据,统一传输至Kafka通道。另外,针对少数不支持log_agent的服务,构建一个日志数据如图中转的应用。日志解析:采集的日志通过Kafka连接到Flink进行统一解析处理。日志按照日志类型进行分类聚合,解析为链路日志、节点日志和业务日志。日志存储:日志分析完成后,日志会以树状存储模型进行存储。基于对存储需求和各存储方案特点的分析,点评内容平台最终选择了HBase作为存储方案。总体来说,log_agent+Kafka+Flink+HBase的日志上报和存储架构可以很好的支持复杂的业务系统,天然支持分布式场景下很多应用的日志上报,也适合大流量的数据写入。②实现了很多后端服务的低成本改造评论内容平台实现了“自定义日志工具包”(即下图13中的TraceLogger工具包),屏蔽了链接跟踪中的报告细节,最大限度地降低了很多成本服务转型。TraceLogger工具包的功能包括:仿slf4j-api:工具包的实现基于slf4j框架,仿slf4j-api对外提供相同的API,用户没有学习成本。屏蔽内部细节,内部封装一系列链接日志上报逻辑,屏蔽染色等细节,降低用户的开发成本。A。上报判断:判断链路ID:没有ID时,自下而上进行日志上报,防止日志丢失。判断上报方式:有标识时,支持日志和RPC传输两种上报方式。b.日志组装:实现参数占用、异常堆栈输出等功能,将相关数据组装成Trace对象,便于统一收集处理。C。异常上报:通过ErrorAPI主动上报异常,兼容原有日志上报中的ErrorAppender。d.日志上报:适配Log4j2日志框架,实现最终的日志上报。图13TraceLogger工具包下面是TraceLogger工具包分别上报业务日志和节点日志的用例,整体改造成本较低。业务日志上报:无学习成本,基本无改造成本。//替换前:将原始日志上报给LOGGER.error("updatestructfailed,param:{}",GsonUtils.toJson(structRequest),e);//替换后:将完整链接日志上报给TraceLogger.error("updatestructfailed,param:{}",GsonUtils.toJson(structRequest),e);节点日志上报:支持API和AOP上报方式,灵活低成本。publicResponserealTimeInputLink(longcontentId){//链接开始:传串口标记(业务标记+场景标记+执行标记)TraceUtils.passLinkMark("contentId_type_uuid");//...//本地调用(API报告节点日志)TraceUtils.reportNode("contentStore",contentId,StatusEnums.RUNNING)contentStore(contentId);TraceUtils.reportNode("contentStore",structResp,StatusEnums.COMPLETED)//...//远程调用ResponseprocessResp=picProcess(contentId);//...}//AOP上报节点日志@TraceNode(nodeName="picProcess")publicResponsepicProcess(longcontentId){//图片处理业务逻辑//业务日志数据上报TraceLogger.warn("picProcessfailed,contentId:{}",contentId);}2)结果基于以上实践,点评内容平台实现了可视化全链路日志追踪,可以通过可视化链接一键追踪任意一条内容所有业务场景的执行情况。执行现场还原,跟踪效果如下图所示:【链接查询功能】:根据内容id实时查询内容所有逻辑链接的执行情况,覆盖所有业务场景。图14链接查询【链接展示功能】:通过链接图直观展示业务逻辑全景图,同时展示各个节点的执行状态。图15链接展示【节点详情查询功能】:支持展示任意一个已执行节点的详情,包括节点输入、输出、节点执行过程中的关键业务日志。图16节点详情目前,可视化全链路日志追踪系统已经成为点评内容平台的“排查利器”。我们可以将故障排除时间从数小时减少到5分钟;它也是一个“测试辅助工具”。日志可视化拼接展示,显着提升RD自测和QA测试效率。最后总结一下可视化全链路日志追踪的优势:访问成本低:DSL配置和简单的日志上报转换即可快速访问。追踪范围广:可追踪任何内容的所有逻辑链接。使用效率高:管理后台支持链接和日志的可视化查询展示,简单快捷。4.总结与展望随着分布式业务系统越来越复杂,可观察性对于业务系统的稳定运行越来越重要。作为大众点评内容管道中复杂的业务系统,为保证内容流通的稳定性和可靠性,大众点评内容平台实现了全链路的可观察构建,在Logging、Metrics和Tracing三个方面都有一定的量勘探建设在特定方向开展。其中之一就是本文的“可视化全链路日志跟踪”。结合日志记录(Logging)和跟踪(Tracing),我们提出了一套新的业务跟踪通用解决方案。通过在业务执行阶段结合完整的业务逻辑动态完成日志的组织级联,替代了传统方案低效滞后的人工日志级联,最终可以实现业务全流程的高效跟踪和业务问题的高效定位。此外,在指标方向,点评内容平台实现了“可视化全链路指标监控”,支持实时、多维度展示业务系统的关键业务和技术指标,并支持相应的告警和异常归因能够有效控制业务系统的整体运行。未来,评论内容平台将持续深耕,实现涵盖告警、概览、排查、分析等功能的可观察系统,并持续沉淀输出相关通用解决方案,希望为业务系统(尤其是复杂业务系统))和对可观察性构建的一些参考和启发。
