导读:架构师非常关注性能问题,上篇文章中我们介绍了京东的自动化压测体系 ForceBot,这篇文章来自 LinkedIn 的技术博客,介绍如何通过大数据算法来分析调用数据,自动定位性能瓶颈。本文由高可用架构翻译。 背景我们是 LinkedIn 的核心性能团队,使命是使 LinkedIn 页面加载更快,我们帮助每个工程团队尝试通过各种优化努力达到页面加载时间目标。 在尝试减少页面加载时间时,我们需要回答的一个常见问题是:性能瓶颈在哪里? 换句话说,工程师应该在哪里集中精力? 通常,为了回答这个问题,性能工程师将研究性能指标,并检查由资源耗时API[1]和调用图[2]捕获的一些样本,并找到调用的热点。 这种方法可能非常有用,但有“尝试和错误”的缺点。 此外,许多示例瀑布数据需要手动点击和分析以找到瓶颈。 我们需要一种系统的方法,即通过工具来分析现有的大量数据,并快速自动定位瓶颈细节。 在本文中,我们将介绍 BOSS(BOttlenecks for Site Speed),这是我们在 LinkedIn 上建立的系统,它分析了数百万瀑布调用样本,并自动识别瓶颈以提高性能。 为什么瓶颈分析很难?人工来定位瓶颈存在一系列问题
在下面的文字中,我们将解释我们如何通过 BOSS 解决这些挑战。 建立调用树模型以统一性能数据源自动化分析的最艰难的部分是将各种数据源放在一起。我们在客户端和服务器端都有性能跟踪数据。这些数据集分开放置且格式各不相同。为了解决这个问题,我们构建了一个通用的调用树模型来将数据粘合在一起。 最终用户的一次点击将导致对多个系统的多个请求。如下图所示,一个典型的页面视图包含对数据中心的 API 请求,image / JS / CSS 请求到 CDN,以及一些向第三方(如广告)的请求。这些请求分布到多个系统,我们需要一种方法在一个地方跟踪它们。 (点击图片可以缩放) 图长得什么样子?对,一颗树! 在 LinkedIn 上,我们已经在不同的服务之间构建了调用树,这些服务位于数据中心内部。如果我们将这个概念应用于其他系统,如CDN,第三方广告,浏览器等,我们会得到一个更大的调用树。 简化客户端调用瀑布图我们使用 Resource Timing 数据来构建客户端调用树模型。然而,原始瀑布包含许多页面级导航定时指标,例如重定向持续时间,第一字节时间,页面下载时间等,以及与页面 HTTP 调用相关联的所有下载的一百多个资源定时条目具有不同的 URL 和资源类型。这使得很难确定慢度的原因。瓶颈需要采取行动。例如,如果个人资料图片通常下载缓慢,则意味着我们的媒体 CDN 需要调查,而不是每个人的个人资料图片。 为了解决这个问题,我们想出了分配给瀑布中每个资源/度量的瓶颈类型,以便获得可操作的瓶颈分析。
注意,我们看到了瀑布中没有网络活动发生的很多时间差距。 在本地调试之后,我们发现在这些空白期间有很多沉重的本地代码执行(js /解析/渲染)。 为了更准确地衡量这一点,我们开始使用用户计时 API 来测量关键的渲染路径,以便我们获得更多的洞察力。 调用树分析一旦我们拥有“组合树”,下一个挑战是如何分析这些树以找到每个页面的性能瓶颈。基本上,有两种调用会损害性能:
开发人员对单个请求的延迟非常敏感,但有时忽略调用并行化的重要性。让我们使用两个假设的网页浏览作为示例。第一个使用 HTML 请求来并行化 CSS 和 JS 调用,但第二个不会。所有调用的延迟是相同的,但页面加载时间有 1,100ms 差异!这里的瓶颈是 HTML 请求阻塞了 CSS 和 JS 请求。 BOSS 认为慢请求和阻塞调用都会造成影响。在上面的示例中,我们的瓶颈分析将给出并行调用 HTML 38.9% 的影响和非并行页面视图的 72.2%。即使每次调用的持续时间是相同的,阻塞 HTML 调用在我们的分析中获得更多的惩罚,并被标记为页面的瓶颈。 要理解计算瓶颈贡献的算法,让我们使用简化版本的页面视图调用树。基于每个调用的开始和结束持续时间将时间线划分为不同的段。对于每个时间段,如果有多个并行发生的调用,我们将均匀地为每个调用贡献此段。 在下面的示例中,90ms 段被分成 3 个部分,并且每个服务被分配 30ms 贡献。对于调用 A 的 100ms 段,没有并行的其他调用,并且它对于整个时间段负责,这将导致对调用 A 有非常高的贡献值。具有高贡献的调用将是最大的瓶颈。因此,调用 A 获得 195ms,这是总页面加载时间 320ms 的 60.9%,由于第一个 100ms 阻塞段加上其长持续时间。调用 B 获得 20.3%,调用 C 获得 18.8%,因为它们彼此并行。 分析大规模的性能瓶颈处理调用树数据是非平凡的。我们获得了数百万的页面访问记录,每个记录创建了一个带有数百个节点的调用树。这里是我们的数据处理系统的要求和我们选择的解决方案:
使用可扩展的数据分析系统,下一个挑战是构建一个算法来分析调用树。 可视化瓶颈分析:聚合所有信息在 UI 方面,我们构建了以下组件来协助分析:
(点击图片可以缩放) 在同一个UI上,用户还可以在散点图中查看页面查看的延迟分布,并单击每个点以获取页面的完整瀑布。 (点击图片可以缩放) 有了这个强大的工具,用户可以轻松点击几下找到瓶颈。 现实世界的例子这里是我们在 2016 年 3 月为 LinkedIn 桌面主页运行的瓶颈分析。每种类型的瓶颈都有贡献率,这意味着“通过消除这个瓶颈,我们可以提高多少网站速度”。这里列出了顶尖的瓶颈和解决方案。
找到瓶颈之后,下一步是找到导致瓶颈的特定请求/代码。我们检查了几个瀑布,发现下载广告后经常发生长时间间隙。这表示在下载广告后有大量的 JavaScript 执行,下一个请求正在等待 JavaScript 完成执行。 修复很容易:我们只是使广告加载使用非阻塞的方式,使图像和其他东西可以同时加载。运行 A / B 测试后,我们的主页在页面加载时间上的速度提高了 21%。与此同时,我们发现用户互动率指标有所提升;在推迟广告之后,用户更多地在网站进行互动。 在我们的瓶颈分析数据中,广告调用的停顿时间显著下降。 结论 我们构建了一个瓶颈分析工具 BOSS,可以大规模处理数据并生成可指导操作的优化建议。我们已经有几个成功案例,也计划进行其他改进,包括:
致谢感谢David He和Ritesh Maheshwari的宝贵意见和反馈。 感谢Toon Sripatanaskul他的真棒服务贡献算法。 感谢Swapnil Ghike和Joseph Zemek为这个项目做出的开拓性努力。 并感谢Oliver Tse为我们的热心用户和他的宝贵反馈。 最后,感谢Steven Pham和Dylan Harris在开发BOSS UI方面的帮助。 参考资源
推荐阅读 |