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

2023-11-12

前言

随着美团点评的业务发展,公司的分布式系统变得越来越复杂,我们亟需一个工具能够梳理内部服务之间的关系,感知上下游服务的形态。比如一次请求的流量从哪个服务而来、最终落到了哪个服务中去?服务之间是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<String, String> data)
putOnce(map<String, String> 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,然后是时间戳。

总结

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

美团-分布式会话跟踪系统架构设计与实践 的相关文章

  • 协调能力体现在哪些方面

    协调能力主 要表现在以下几个方面 1 熟悉和掌握组织现有的人 财 物等资源状况 及时进行资源合理 调配 2 了解不同人的需求和能力特点 在人员配置上做到优势互补 3 有效调动他人完成任务的积极性 4 成功解决工作过程中出现的棘手冲突或矛盾
  • Matlab中fprintf函数使用

    目录 说明 示例 输出字面文本和数组值 将双精度值输出为整数 将表格数据写入文本文件 获取写入文件的字节数 在命令行窗口中显示超链接 fprintf函数将数据写入文本文件 fprintf fileID formatSpec A1 An fp
  • chatGPT回答字数限制解除-怎么突破chatGPT长度的限制

    ChatGPT如何写作 ChatGPT 是一种基于机器学习的自然语言处理技术 可以自动生成文本 包括段落 文章 新闻 电子邮件 推文等 以下是使用 ChatGPT 进行写作的基本过程 确定写作内容和细节 首先需要 确定要生成的文本内容和相关
  • Qt——QMainWindow不同功能栏基础操作总结

    目录 一 菜单栏 二 工具栏 三 状态栏 四 浮动窗口 铆接部件 五 中心部件 中心控件 一 菜单栏
  • windows系统下通过Easybcd安装Ubuntu系统

    本文以ubuntu 14 04为例 但其它版本 比如16 04等都是可以的 不想用虚拟机了 想要在win7系统下安装个ubuntu系统 实现双系统 于是在网上各种搜索 然后综合各种方法 在自己的电脑上进行安装 用了两种方法 一种是通过软件的
  • Android 虚拟 A/B 详解(七) 升级中用到了哪些标识文件?

    本文为洛奇看世界 guyongqiangx 原创 转载请注明出处 原文链接 https blog csdn net guyongqiangx article details 129098176 Android 虚拟 A B 分区 Andro
  • Cogvideo:通过变压器进行文本到视频的大规模预处理

    经过大规模的变压器在文本 GPT 3 和文本形象 Dall E和Cogview 一代中创建了里程碑 它在视频生成上的应用仍面临许多挑战 潜在的巨大计算成本使从头开始培训无法承受 文本视频数据集的稀缺性和弱相关性阻碍了理解复杂运动语义的模型
  • 局域网 git服务器 虚拟机,GitLab服务器傻瓜式搭建教程

    开始前的准备 需要有一台Linux系统的服务器或虚拟机 QAQ 安装包下载地址 https mirrors tuna tsinghua edu cn gitlab ce 注 本教程无需下载安装包 以下教程为CentOS8环境所搭建 第一步
  • 华为eNSP实现外网访问内网,DHCP,easyIP配置案例

    一 需求分析 1 五个部门独立的网络管理 分别不同的VLAN 2 VLAN网关在SW1上 3 边界路由器R1与SW1通过三层互联 4 R1上配置转换技术实现VLAN10 20 40 50上网 财务部不许上网 5 R1上通过最节省IP地址方式
  • UE客户端开发需要哪些知识

    进行UE客户端开发需要以下知识 C 编程语言 UE客户端使用C 作为主要编程语言 因此需要对C 的语法 STL容器 面向对象编程等有深入的理解 Unreal Engine框架 了解UE框架的各个模块 例如Gameplay Framework
  • 单链表的基本操作-单链表的创建、插入、删除结点等

    序言 本文主要包括 1 单链表的创建 2 创建结点 3 打印结点 4 链表的插入 头插法 5 链表的删除 指定位置删除 适合新手初步认识学习单链表的基本操作 各个操作都在一起 也有注释 欢迎大家留言讨论 一 代码 include
  • 动态网站开发02:Java web

    动态网站开发02 一 前言 二 笔记 一 XML基础 1 XML概述 2 XML与HTML的比较 二 XML语法 1 XML文档的声明 2 XML元素的定义 3 XML属性的定义 4 XML注释的定义 5 XML文件示例 三 DTD约束 1
  • 爆肝近3万字解读:程序员必须掌握哪些算法?(含算法的代码实现)

    一个程序员一生中可能会邂逅各种各样的算法 但总有那么几种 是作为一个程序员一定会遇见且大概率需要掌握的算法 今天就来聊聊这些十分重要的 必抓 算法吧 一 引言 1 1 算法的重要性 算法的重要性体现在以下几个方面 解决问题 算法是解决问题的
  • 渗透测试工具备忘单

    https highon coffee blog penetration testing tools cheat sheet
  • @FeignClient使用详细教程(图解)

    FeignClient使用详细教程图解 作用 FeignClient标签的常用属性 使用流程 通俗解释可以把它当成一个spring Bean 可以直接当成一个Service 给 FeignClient 添加Header信息 作用 Feign
  • O2O B2B B2C C2C P2P 名词解释

    O2O O2O 是Online To Offline的缩写即在线离线 线上到线下 是指将线下的商务机会与互联网结合 让互联网成为线下交易的平台 这个概念最早来源于美国 O2O的概念非常广泛 既可涉及到线上 又可涉及到线下 可以通称为O2O
  • go time包

    定时器 在time包中有两个函数可以帮助我们初始化time Timer time Newtimer函数 初始化一个到期时间据此时的间隔为3小时30分的定时器 t time Newtimer 3 time Hour 30 time Minut
  • python使用matplotlib的pyplot库进行绘制堆叠直方图

    先上代码 2020 3 27 中国 CN 82213 184 75122 3301 3790 2020 3 27 英国 GB 14579 0 150 759 13670 2020 3 27 日本 JP 1507 0 359 51 1097
  • 我的python3.6、opencv安装环境搭建

    我需要使用tesseract OCR的模块 vs的配置有点麻烦 所以采用py的环境 搭建 1 在python org网站下载python3 6版本 我下载的3 6 8的python的安装 选存放的路径和把配置环境变量选项勾上否则需要自己配置

随机推荐

  • python爬虫经典案例,看完这一篇就够了

    urllib2 urllib2是Python中用来抓取网页的库 urllib2 是 Python2 7 自带的模块 不需要下载 导入即可使用 在python2 x里面有urllib和urllib2 在python3 x里面就把urllib和
  • 美云MES成长史:生于美的 长在美云智数

    每一种新技术的迭代 就犹如一次生命的洗礼 美云MES的成长 也经历过这种洗礼 2016年11月份 美云智数带着美的基因走上了创业之路 其5大产品体系16个Saas产品 不仅融合了深厚的技术底蕴 还继承了世界500强宝贵的实践经验 以跨界融合
  • 案例一:将 1-100 之间的所有正整数存放在一个 List 集合中,并将集合中索引位置是 10 的对象从集合中移除。

    package Homework 01 import java util ArrayList import java util List 将 1 100 之间的所有正整数存放在一个 List 集合中 并将集合中索引位置是 10 的对象从集合
  • CMakeLists编译静态库与动态库

    一 编写一个库 编写一个计算整数和浮点数之和的库函数mymath 文件目录 mymath h ifndef MYMATH H define MYMATH H int add int int double add double double
  • 关于idea 右键找不到Diagrams 按钮(类的继承关系图)

    在idea的setting的plugin里面已下载的找到JBoss 查看是否开启 如果没有开启 点击enable 后重启idea 即可
  • 用Python做兼职是如何挣钱的?

    我当时学习python大概有半年的时间 学的还可以 后面一个认识的朋友给我介绍了一点私活 当时接单赚了2K左右 后又自己接过开发网站后台接口 做数据处理等事情 七七八八的加起来也有一些收入 其实我学python也是凑巧 我本身是学电商的 后
  • 用例模型与概念模型的区别和联系

    1 首先研究它究竟是什么 what 三者的定义 用例 即use case 一种描述系统需求的方法 用例建模 使用用例的方法来描述系统需求的过程 概念模型 是现实世界到机器世界的一个中间层次 2 怎样关联的 how 分析业务过程 建立用例模型
  • 翻译:Attention Is All You Need

    摘要 主要序列转导模型基于包括编码器 encoder 和解码器 decoder 的复杂递归或卷积神经网络 性能最佳的模型还通过注意机制连接编码器和解码器 我们提出了一种新的简单网络架构 Transformer 完全基于注意机制 based
  • 结构化开发方法--结构化分析方法

    说在前面 本系列文章专注于软考备考复习内容梳理 文章内容是对教材中知识点和考点的提炼 备考过程中可以有针对的进行复习 减少阅读量 有的放矢 导航目录 一 结构化分析方法概述 二 数据流图 三 数据字典 DD 结构化分析与设计方法是一种面向数
  • PyQt5 音乐播放器实现

    PyQt5 音乐播放器 import sys from PyQt5 QtWidgets import QApplication QMainWindow QFileDialog QListWidgetItem from PyQt5 QtCor
  • 【计算机基础知识8】深入理解OSI七层模型

    目录 一 前言 二 OSI七层模型概述 三 第一层 物理层 四 第二层 数据链路层 五 第三层 网络层 六 第四层 传输层 七 第五层 会话层 八 第六层 表示层 九 第七层 应用层 十 OSI七层模型与实际网络通信的关系 十一 总结 一
  • Flask + Flask-socketio 实现简单的 WebServer(可与C++程序进行通信)

    Flask Flask socketio 实现简单的 WebServer 最近手头上的项目要给树莓派上的一个程序实现一个web客户端 公司之前用的goahead c 实现的 正好最近在看Python 鉴于python有强大的web开发框架
  • Firefox火狐浏览器显示你的连接不安全,是什么意思?

    当 Firefox 连接到一个安全的网站时 网址最开始为 https 它必须确认该网站出具的证书有效且使用足够高的加密强度 以充分保护您的隐私 如果证书无法通过验证 或加密强度过低 Firefox 会中止连接到这个网站 并向您显示SSL证书
  • 纯代码干货-Python基于YOLOv5的车辆检测并计数

    首先 你需要安装YOLOv5 可以通过官方文档了解安装步骤和相关依赖 接着 你需要准备训练好的车辆检测模型和测试图片或视频 1 导入库 import cv2 import torch from models experimental imp
  • sqlite 在实现记录存在即更新,不存在就插入

    在一次写sql语句的时候突发奇想 为什么不能把插入和更新记录写在一起呢 这样一条语句就能完成两个操作了 而且有时候可能也会碰到需要这样的逻辑 于是找了还真有 但是由于sqlite是比较小型的数据库所以具体方式不太一样 insert into
  • RS485通信与Modbus协议 附源码下载

    RS485通信与Modbus协议 附源码下载 RS485通信的特点 1 采用差分信号 2 RS485通信速率快 最大传输速率可以达到10Mb s以上 3 RS485内部采用平衡驱动器和差分接收器的组合 抗干扰能力大大增加 4 传输距离最远可
  • android播放gif图片,Android SurfaceView 播放gif

    Android SurfaceView 是Android系统中的高级组件 它有自己的绘制界面 可以在一个独立的线程进行UI的绘制 因此不会阻塞主线程 这也是我们使用SuefaceView播放gif图片的原因 先简单说一下思路 gif图其实就
  • Openwrt编译python3时出现错误:No rule to make target `package//host/compile'

    步骤 1 在package目录下添加python3 包含Makefile files和相关patches文件 2 执行make package python3 compile V s make 1 No rule to make targe
  • 纯css3制作手风琴选项卡

    前言 平时工作中时常会制作手风琴以及选项卡 制作这些我们首先想到的是使用 js 操作 而其实 css3 也是可以完成 不需要使用 js 下面我们就使用 css3 完成 效果如下 手风琴 结构代码如下 ul class box li li u
  • 美团-分布式会话跟踪系统架构设计与实践

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