Facebook Canopy 初探

Stella981
• 阅读 768

原创声明:本文系作者原创,谢绝个人、媒体、公众号或网站未经授权转载,违者追究其法律责任。

Google Dapper

首先简单回顾一下 Google 的 Dapper,2010 年 Google 发布 Dapper 的论文系统阐述了在复杂的、大规模分布式集群环境下如何进行系统的跟踪以及问题的分析与定位。通过产生一个全局唯一的 traceId 以及用 span、annotation 核心数据模型把相关调用组成一个完整的调用树。关于 Dapper 如何做低消耗、应用级透明等细节,可以参考 Dapper 的论文。这里主要是简单回顾一下其核心思想,因为后续出现的分布式跟踪产品包括本文要分析的 Facebook 的 Canopy 都有受其启发。此文是基于2017年 Facebook 发布的 Canopy 论文,分析其如何进行分布式跟踪以及问题分析定位。

Facebook Canopy 初探

Span在 Dapper 跟踪树种短暂的关联关系

图片出自 Google Dapper[1]

背景介绍

TMM

在 Canpoy 产品前,Facebook 有一个产品叫 TMM(The Mystery Machine),在其 2014 年的论文中有具体描述,简单看一下其架构如下:

Facebook Canopy 初探

将 trace 数据存储到 Hive、Scribe 中,然后通过 Hadoop 去跑 job 去分析计算其 trace 模型。从 1.3M 条 trace 数据中分析计算出相关模型需要 2 个小时,分析还是依赖离线计算能力上,实时性没有那么强。

Canopy

在互联网分布式环境下,每一个系统在其特定场景下都有其特殊性,各自的模型都有其不同点,无法继承如  RPC 场景、Event Loop、浏览器页面加载、Mobile App 等,如果为某些场景定制化,会面临这些场景的迭代开发时间长。

另一方面一些性能分析工具不能跨系统进行分析,需要掌握每一种场景下应该使用什么样的分析工具以及相关数据之间的映射关系。每一种工具都有其开发周期,部署时间较长。基于此 Facebook 设计开发 Canopy 的出发点很明确主要是进行单个或跨系统间性能问题的定位,对一些问题分析的推测进行快速验证。

Canopy 于 2015 年开始在生产环境投入使用,每天产生和处理 13 亿数据量,整个产品是作为替换 TMM 在进行演进。

示   例

首先通过一个分析诊断问题的示例来看一下 Canopy 是如何去定位问题的。在此之前,先简单说下 Facebook 页面显示的一些技术点。Facebook 显示的一个完整的页面是有很多由不同团队开发的 page pieces 组成。Facebook 的核心框架会将它们进行合并在 web servers 和用户的浏览器端运行。为了优化用户体验,会用到一种 Early Flush 技术。Early-Flush 是服务端的一种优化技术手段,实现预测客户端需要的资源,批量发送给客户端。

问题描述,Facebook.com 在显示某个页面的初始化平均响应时间增加了300ms,如 a) 图显示:

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

通过页面加载延时看到其延时增加 300ms,但没法定位到具体的某部分导致其增加,在此基础上进行进一步的拆解分析,如 b) 图显示:

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

从图分析服务后端的 server 以及网络相关延时都没有发生变化,但浏览器执行时间以及资源 (css,js 等) 的获取时间增加了。很自然接下来去分析资源加载这块的问题如 c) 图所示:

Facebook Canopy 初探

图片出自Facebook Canopy[2]

页面初始化显示需要的资源发现 css 的资源下降了 5%,同时发现 Early-Flush 图有一次 miss,导致 css 额外加载了 10KB 的数据,如 d) 图所示:

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

通过这些 metrics 已经知道问题所在(Early-Flush 没有命中),但还不知道具体是哪一部分导致,所以进行进一步的拆解,按 page pieces 进行分组,找到 root cause 是 UserInput 部分导致资源的加载如 e) 图所示:

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

分析 UserInput 因增加的新的功能有变动,需要一些新的资源,但 Early-Flush 组件并不知道其发生了变更,从而没有达到的优化的效果,通过调整 Early-Flush 相关配置,性能问题从而解决。这是一个很常见的因相关配置没有进行修改而导致性能问题的 case,但往往这种问题很难发现定位到。

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

挑 战

从上面的示例中可以看出,后面需要很丰富、详细的 trace 以及 metrics 数据进行分析、拆解。挑战主要体现在如下几个方面:

  • Trace数据的模型

    直接操作海量的基本的性能数据是非常笨重的,扩展上也不太可能。工程师和使用的工具都必须理解底层的事件数据与各组件高层次(High level)的数据之间的映射关系。但如果建立一个高层次的固化的模型又会带来问题:已经存在的组件,已经未来新的组件,以及三方的组件的如何支持进来。如果用多种执行模型,性能数据粒度以及质量存在大幅度变化,性能数据多样化,无法统一。因此 trace 模型的如何管理非常关键。在 Dapper 中 Span 来表示树形层次关系,在模型方面 Dapper 用 Span 来表示树形层次

  • 数据的分析

在数据量大的情况下提供从多特征角度进行切分、分组、过滤、组合及汇总 trace 数据

  • 满足通用以及个性化需求

 对于一些常用场景的一般的用法支持的情况下,具备支持个性化需求的能力来满足不同场景的需求。

设  计

这部分主要看 Canopy 是如何设计去满足以及迎接这些挑战。

Pipeline

通过管道机制,从系统生成的跟踪数据中提取性能数据。在管道的每一个阶段,给用户的提供定制能力,并且各个组件之间的关注点是隔离的,这样可以进行彼此的演进而不互相影响。

Canopy 的 trace 数据的收集的思路和 Dapper 类似,也是基于一些通用的组件进行 instrument,产生一个 traceId,然后在各个组件中进行传递,产生相关的事件,Canopy Event 会在后续介绍。

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

产生的事件会已上报进行收集处理,以下是其主要处理流程

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

④ 事件中带有执行过程中的相关性能数据以及依赖(因果)关系数据

⑤ 收到数据在内存中进行聚合

⑥ 落地存储

⑦ 如果一个请求的所有事件收齐,然后就排队处理,在 Canopy 中所有和跟踪相关数据都已事件方式上报,需要确保一次完整的链路数据已经收齐

⑧ 把 trace event 事件映射成 trace model,因为 trace 事件中包含了相关数据能以此进行模型的重构

⑨ 执行 feature 表达式,从已经模型化的 trace中抽取计算需要的特征数据,从这块可以支持一些定制化的需求

⑩ 表达式中通过dataset配置绑定自己感兴趣的过滤掉自己不需要的 trace,以及数据的输出配置

⑪ 自己查询 dataset,或查看视图和 Dashboard

⑫ 除了可以自定义 dataset,也提供了共享的(通用)dataset,一些通用的high-level特性进行查询视图以及 Dashboard,以及一些工具用下钻分析。

以上介绍了 Canopy 的主体流程,通过 Canopy 的 events 把所有 trace 数据进行上报存储,在 Instrumentation API 层都是基于 events 携带需要的 trace 信息,而没有特定的数据模型进行封装,而在数据收集后可以进行很灵活的模型重建以及数据的抽取。

下面来看起各个相关点的设计。

Instrumentation APIs

主要职责

  • 产生 traceId,并负责传递

  • 记录请求相关的结构层次(e.g. 何时何地,线程和组件因果关系,网络通信)

  • 收集有用的性能数据

解耦设计

  • 特定的 Instrumentation 任务应该访问有限的 API,这样降低接入门槛减少出错,产生一些不正常的 trace 数据

  • 访问这些有限的 API (封装好相关逻辑),产生的数据相比自己去构建数据更健壮

  • 从多个角度捕获性能相关的数据,而不会破坏已经存在的逻辑。这样可以很好的支持自定义需求的设计以及与第三方包的集成

Trace Event

Trace Event

Trace Event

Canopy中的 event 结构信息:

Facebook Canopy 初探

图片出自 Facebook Canopy[2]

Event type 可扩展,会根据 type 来做不同的处理,sequenceNumber 和 timestamp 主要用于将同一个进程或线程中的 event 排序,EventId(RandomId) 用于关联其他有关系的 event。会在发送方记录 eventid,traceId 和 eventid  都会透传给接收方,在接收方会记录发送者的 eventid。

Modeled Traces

根据 event 来构建 Modeled Trace,性能数据 High-Level 表现形式,隐藏了底层日志事件的不一致性。

类型

  • Execution units:执行线程

  • Blocks:execution unit中计算段(Segments of computation within an execution unit)

  • Points:一个Block中即时发生的events

  • Edge:points间的因果关系

    可以表示进程间或机器间的因果关系也可用于表示同一进程中的execution units或blocks。非常适合以下模式

    长时间运行的执行单元间的流,双向通讯,应用级别block依赖

Trace Datasets

  • Trace 数据衍生出来的数据集,囊括了很多Traces数据的信息

  • 性能分析的主要入口点(面向工程师)

  • Feature(trace中一个元素的label或聚合值或一些结构关系) 通过抽取函数(抽取函数是无状态的且一条trace记录执行一次)产生

Facebook Canopy 初探

Trace Dataset 表现形式

基于这些丰富或自定义的 trace 数据集来支持一般以及个性化需求。

小  结

本文介绍了 Facebook Canopy 在面对海量 trace 数据以及各种环境下,如何去设计端到端的性能分析产品。纵观下来,其设计特点是解耦的设计,trace 事件数据没有绑定到固定的数据模型中,数据处理环节支持灵活的 feature 抽取,形成不同的 trace dataset 数据集来达到不通场景的需求。

参考

[1] Dapper, a Large-Scale Distributed Systems Tracing Infrastructure

[2] Canopy: An End-to-End Performance Tracing and Analysis System

Facebook Canopy 初探

Facebook Canopy 初探

长按二维码关注我们  ▶▶▶

Facebook Canopy 初探

Facebook Canopy 初探

点击“阅读原文”获取招聘信息

本文分享自微信公众号 - 金融级分布式架构(Antfin_SOFA)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
CSS 奇思妙想:超级酷炫的边框动画
点上方蓝字关注公众号「前端从进阶到入院」精选原创好文助你进入大厂文章转载自公众号「iCSS前端趣闻」今天逛博客网站shoptalkshow\1\,看到这样一个界面,非常有意思:!(https://oscimg.oschina.net/oscnet/9655b35af5a045999ff55c144a3f7c
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这