热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分布式会话跟踪系统架构设计与实践

本文整理自美团点评技术沙龙第08期:大规模集群的服务治理设计与实践。美团点评技术沙龙由美团点评技术团队主办,每月一期。每期沙龙邀请美团点评及其它互联网公

本文整理自美团点评技术沙龙第08期:大规模集群的服务治理设计与实践。

美团点评技术沙龙由美团点评技术团队主办,每月一期。每期沙龙邀请美团点评及其它互联网公司的技术专家分享来自一线的实践经验,覆盖各主要技术领域。

目前沙龙会分别在北京、上海和厦门等地举行,要参加下一次最新沙龙活动?赶快关注微信公众号“美团点评技术团队”。

这期沙龙主要内容有:分布式服务通信框架及服务治理系统、分布式监控系统实践、分布式会话跟踪系统架构设计与实践,特邀美恰CTO讲解时下热门话题“微服务”。其中既包括关键系统设计、在美团点评内部的实践经验,也包括一些项目在业界开源的运营实践。

前言

随着美团点评的业务发展,公司的分布式系统变得越来越复杂,我们亟需一个工具能够梳理内部服务之间的关系,感知上下游服务的形态。比如一次请求的流量从哪个服务而来、最终落到了哪个服务中去?服务之间是RPC调用,还是HTTP调用?一次分布式请求中的瓶颈节点是哪一个,等等。

简介

MTrace,美团点评内部的分布式会话跟踪系统,其核心理念就是调用链:通过一个全局的ID将分布在各个服务节点上的同一次请求串联起来,还原原有的调用关系、追踪系统问题、分析调用数据、统计系统指标。这套系统借鉴了2010年Google发表的一篇论文《dapper》,并参考了Twitter的Zipkin以及阿里的Eagle Eye的实现。
那么我们先来看一下什么是调用链,调用链其实就是将一次分布式请求还原成调用链路。显式的在后端查看一次分布式请求的调用情况,比如各个节点上的耗时、请求具体打到了哪台机器上、每个服务节点的请求状态,等等。它能反映出一次请求中经历了多少个服务以及服务层级等信息(比如你的系统A调用B,B调用C,那么这次请求的层级就是3),如果你发现有些请求层级大于10,那这个服务很有可能需要优化了。

网络优化

如上图所示,红框内显示了一次分布式请求经过各个服务节点的具体IP,通过该IP就可以查询一次分布式请求是否有跨机房调用等信息,优化调用链路的网络结构。

瓶颈查询

再比如上图,红框部分显示的是系统调用的瓶颈节点,由于该节点的耗时,导致了整个系统调用的耗时延长,因此该节点需要进行优化,进而优化整个系统的效率。这种问题通过调用链路能很快发现下游服务的瓶颈节点;但是假如没有这样的系统,我们会怎样做呢?首先我会发现下游服务超时造成了我的服务超时,这时我会去找这个下游服务的负责人,然后该负责人发现也不是他自己服务的问题,而是他们调用了其他人的接口造成的问题,紧接着他又去找下游的服务负责人。我们都知道跨部门之间的沟通成本很高的,这么找下去会花费大量的不必要时间,而有了MTrace之后,你只需要点开链路就能发现超时问题的瓶颈所在。

优化链路

我们再来看下上面这张图,红框部分都是同一个接口的调用,一次请求调用相同的接口10几次甚至是几十次,这是我们不想看到的事情,那么整个系统能不能对这样的请求进行优化,比如改成批量接口或者提高整个系统调用的并行度?在美团点评内部我们会针对这样的链路进行筛选分析,然后提供给业务方进行优化。

异常log绑定

通过MTrace不仅能做上述这些事情,通过它的特性,还能携带很多业务感兴趣的数据。因为MTrace可以做到数据和一次请求的绑定以及数据在一次请求的网络中传递。比如一些关键的异常log,一般服务的异常log很有可能是因为上游或者下游的异常造成的,那就需要我们手动地对各个不同服务的异常log做mapping。看这次的异常log对应到上游服务的哪个log上,是不是因为上游传递的一些参数造成了该次异常?而通过MTrace就可以将请求的参数、异常log等信息通过traceId进行绑定,很容易地就把这些信息聚合到了一起,方便业务端查询问题。

透明传输数据

业务端往往有这样的需求,它希望一些参数能在一次分布式请求一直传递下去,并且可以在不同的RPC中间件间传递。MTrace对该类需求提供了两个接口:

put(map data)
putOnce(map data)

  • put 接口:参数可以在一次分布式请求中一直传递。
  • putOnce 接口:参数在一次分布式请求中只传递一级。

如下图所示

  • 左侧绿色部分是put接口,service中调用了put接口传递了uid=123456这个参数,它会在网络中一直传递,可以在服务A中通过get("uid")的方式获取参数值,也可以在服务C中通过get("uid")的方式获取参数值。
  • 右侧蓝色部分是putOnce接口,service中调用了putOnce接口传递pid=11111,它只会传递一级,可以在服务B中通过get("pid")的方式获取参数值,但是在服务D中就获取不到pid的值了。

以上的两种接口可以用于业务自定义传递数据,比如通过传递一个服务标识,用于AB test,下游的所有服务获取到test的标识就会走test的策略,即上游服务可以传递一些参数,控制所有下游服务的逻辑。当然业务也可以通过该接口传递一些临时性的数据。

系统架构

主要分为三层:数据埋点上报、数据收集计算、数据前端展示。

基本概念

traceId

全局唯一,64位整数,用于标识一次分布式请求,会在RPC调用的网络中传递。

spanId

签名方式生成:0, 0.1, 0.1.1, 0.2。用于标识一次RPC在分布式请求中的位置,比如0.2就是0节点服务调用的第二个服务。

annotation

业务端自定义埋点,业务感兴趣的想上传到后端的数据,比如该次请求的用户ID等。

数据埋点

埋点SDK

提供统一的SDK,在各个中间件中埋点,生成traceID等核心数据,上报服务的调用数据信息。

  • 生成调用上下文;
  • 同步调用上下文存放在ThreadLocal, 异步调用通过显式调用API的方式支持;
  • 网络中传输关键埋点数据,用于中间件间的数据传递,支持Thrift, HTTP协议。

业内有些系统是使用注解的方式实现的埋点,这种方式看似很优雅,但是需要业务方显式依赖一些AOP库,这部分很容易出现问题,因为AOP方式太过透明,导致查问题很麻烦,而且业务方配置的东西越多越容易引起一些意想不到的问题,所以我们的经验是尽量在各个统一的中间件中进行显式埋点,虽然会导致代码间耦合度增加,但是方便后续定位问题。其次,为了整个框架的统一,MTrace并非仅支持Java一种语言,而AOP的特性很多语言是不支持的。

Agent

  • 透传数据,用作数据转发;
  • 做流量控制;
  • 控制反转,很多策略可以通过agent实现,而不需要每次都升级业务代码中的SDK。

Agent仅仅会转发数据,由Agent判断将数据转发到哪里,这样就可以通过Agent做数据路由、流量控制等操作。也正是由于Agent的存在,使得我们可以在Agent层实现一些功能,而不需要业务端做SDK的升级,要知道业务端SDK升级的过程是很缓慢的,这对于整个调用链的系统来说是不可接受的,因为MTrace整个系统是针对庞大的分布式系统而言的,有一环的服务缺失也会造成一定的问题。

目前MTrace支持的中间件有:

  • 公司内部RPC中间件
  • http中间件
  • mysql中间件
  • tair中间件
  • mq中间件

数据埋点的四个阶段:

  • Client Send : 客户端发起请求时埋点,需要传递一些参数,比如服务的方法名等

    Span span = Tracer.clientSend(param);

  • Server Recieve : 服务端接收请求时埋点,需要回填一些参数,比如traceId,spanId

    Tracer.serverRecv(param);

  • ServerSend : 服务端返回请求时埋点,这时会将上下文数据传递到异步上传队列中

    Tracer.serverSend();

  • Client Recieve : 客户端接收返回结果时埋点,这时会将上下文数据传递到异步上传队列中

    Tracer.clientRecv();

埋点上下文

上图CS、SR为创建上下文的位置,CR、SS为归档上下文的位置。

上下文归档

上下文归档,会把上下文数据异步上传到后端,为了减轻对业务端的影响,上下文上报采用的是异步队列的方式,数据不会落地,直接通过网络形式传递到后端服务,在传递之前会对数据做一层压缩,主要是压缩比很可观,可以达到10倍以上,所以就算牺牲一点CPU资源也是值得的。具体上报的数据如图所示:

我们之前在数据埋点时遇到了一些问题:

  • 异步调用
    • 异步IO造成的线程切换,不能通过ThreadLocal传递上下文。
    • 显式的通过API进行埋点传递,切换前保存,切换后还原。
    • 提供封装好的ThreadPool库。
  • 数据量大,每天千亿级别的数据
    • 批量上报
    • 数据压缩
    • 极端情况下采样

数据存储

Kafka使用

我们在SDK与后端服务之间加了一层Kafka,这样做既可以实现两边工程的解耦,又可以实现数据的延迟消费。我们不希望因为瞬时QPS过高而引起的数据丢失,当然为此也付出了一些实效性上的代价。

实时数据Hbase

调用链路数据的实时查询主要是通过Hbase,使用traceID作为RowKey,能天然的把一整条调用链聚合在一起,提高查询效率。

离线数据Hive

离线数据主要是使用Hive,可以通过SQL进行一些结构化数据的定制分析。比如链路的离线形态,服务的出度入度(有多少服务调用了该服务,该服务又调用了多少下游服务)

前端展示

前端展示,主要遇到的问题是NTP同步的问题,因为调用链的数据是从不同机器上收集上来的,那么聚合展示的时候就会有NTP时间戳不同步的问题,这个问题很难解决,于是我们采取的方式是前端做一层适配,通过SpanId定位调用的位置而不是时间,比如0.2一定是发生在0.1这个Span之后的调用,所以如果时间出现漂移,就会根据SpanId做一次校正。即判断时间顺序的优先级为最高是spanid,然后是时间戳。

总结

核心概念:调用链;
用途:定位系统瓶颈,优化系统结构、统计系统指标、分析系统数据;
架构:埋点上报、收集计算、展示分析。

分布式会话跟踪系统主要的特点就是能关联服务之间的联动关系,通过这层关系可以延伸出来很多有意义的分析数据,统计数据。为优化系统结构,查询系统瓶颈问题带来了极大的便利。




发现文章有错误、对内容有疑问,都可以关注美团点评技术团队微信公众号(meituantech),在后台给我们留言。我们每周会挑选出一位热心小伙伴,送上一份精美的小礼品。快来扫码关注我们吧!



推荐阅读
  • 阿里面试题解析:分库分表后的无限扩容瓶颈与解决方案
    本文探讨了在分布式系统中,分库分表后的无限扩容问题及其解决方案。通过分析不同阶段的服务架构演变,提出了单元化作为解决数据库连接数过多的有效方法。 ... [详细]
  • 深入解析轻量级数据库 SQL Server Express LocalDB
    本文详细介绍了 SQL Server Express LocalDB,这是一种轻量级的本地 T-SQL 数据库解决方案,特别适合开发环境使用。文章还探讨了 LocalDB 与其他轻量级数据库的对比,并提供了安装和连接 LocalDB 的步骤。 ... [详细]
  • 本项目使用Java语言开发了一个基于B/S架构的指纹识别系统,该系统能够实现指纹的高效采集与精准识别,适用于多种安全认证场景。 ... [详细]
  • 本文介绍了一种在 Android 开发中动态修改 strings.xml 文件中字符串值的有效方法。通过使用占位符,开发者可以在运行时根据需要填充具体的值,从而提高应用的灵活性和可维护性。 ... [详细]
  • 本文由公众号【数智物语】(ID: decision_engine)发布,关注获取更多干货。文章探讨了从数据收集到清洗、建模及可视化的全过程,介绍了41款实用工具,旨在帮助数据科学家和分析师提升工作效率。 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • Hyperledger Fabric 1.4 节点 SDK 快速入门指南
    本文将详细介绍如何利用 Hyperledger Fabric 1.4 的 Node.js SDK 开发应用程序。通过最新版本的 Fabric Node.js SDK,开发者可以更高效地构建和部署基于区块链的应用,实现数据的安全共享和交易处理。文章将涵盖环境配置、SDK 安装、示例代码以及常见问题的解决方法,帮助读者快速上手并掌握核心功能。 ... [详细]
  • 优雅地记录API调用时长
    本文旨在探讨如何高效且优雅地记录API接口的调用时长,通过实际案例和代码示例,帮助开发者理解并实施这一技术,提高系统的可观测性和调试效率。 ... [详细]
  • 本文介绍了基于Java的在线办公工作流系统的毕业设计方案,涵盖了MyBatis框架的应用、源代码分析、调试与部署流程、数据库设计以及相关论文撰写指导。 ... [详细]
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 本文详细介绍了 Node.js 中 OS 模块的 arch 方法,包括其功能、语法、参数以及返回值,并提供了具体的使用示例。 ... [详细]
  • 本文详细介绍了在CentOS 6.5 64位系统上使用阿里云ECS服务器搭建LAMP环境的具体步骤。首先,通过PuTTY工具实现远程连接至服务器。接着,检查当前系统的磁盘空间使用情况,确保有足够的空间进行后续操作,可使用 `df` 命令进行查看。此外,文章还涵盖了安装和配置Apache、MySQL和PHP的相关步骤,以及常见问题的解决方法,帮助用户顺利完成LAMP环境的搭建。 ... [详细]
author-avatar
520sweet跃_322
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有