Heroku 上奇怪的 TTFB(第一个字节的时间)问题

2024-01-08

我们正在改进 Heroku 上托管的 Rails 应用程序(rails 3.2.8 和 ruby​​ 1.9.3)的性能。在此期间,我们遇到了一个令人震惊的问题,其来源似乎极难追踪。让我快速解释一下我们如何遇到这个问题以及我们如何尝试隔离它。

--

自六月左右以来,我们在整个网站的“首字节时间”方面都经历了奇怪的滞后行为。使用该网站时问题很明显(有时应用程序在 10-20 秒内没有响应),并且它也存在于通过pagetest.org 进行的瀑布分析中。 我们的总部位于丹麦,但可以从任何主机处获得此结果。

为了确认该问题,我们执行了基准测试,向一个简单页面发送 300 个相同的请求并测量响应时间。 如果我们向首页发送 300 个请求,中位响应时间低于 1 秒,这相当不错。让我们害怕的是,60 个请求花费的时间是两倍多,其中 40 个请求花费的时间超过 4 秒。有些请求需要长达 16 秒的时间。

这些缓慢的请求都不会出现在我们用于性能监控的 New Relic 中。不会出现任何请求排队,无论我们将 Web 流程扩展至多高,结果都是相同的。 尽管如此,我们不能否认问题是由应用程序代码引起的,因此我们尝试了另一个实验,通过机架中间件响应请求。

通过将此中间件 (TestMiddleware) 放置在机架堆栈的开头,我们在请求到达应用程序之前就返回了请求,确保以下中间件或 Rails 应用程序都不会导致延迟。

Middleware setup:
$ heroku run rake middleware
use Rack::Cache
use ActionDispatch::Static
use TestMiddleware
use Rack::Rewrite
use Rack::Lock
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::DalliStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
use NewRelic::Rack::BrowserMonitoring
use Rack::RailsExceptional
use OmniAuth::Builder
run AU::Application.routes

然后,我们运行相同的脚本来记录响应时间,并得到几乎相同的结果。中值响应时间约为 130 毫秒(显然更快,因为它不会影响应用程序。但仍有 60 个请求花费了超过 400 毫秒,25 个请求花费了超过 1 秒。同样,有些请求慢至 16 秒。

一种解释可能与网络上的缓慢跳跃或 DNS 设置有关,但跟踪路由的结果看起来完全正常。

这个结果通过在 Heroku 上托管的另一个 Rails 3.2 和 ruby​​ 1.9.3 应用程序上运行响应脚本得到了证实 - 根本没有奇怪的行为。

DNS 设置遵循 Heroku 的建议。

--

至少可以说我们很困惑。 Heroku 的路由网络是否存在可疑之处? 为什么我们会看到这种奇怪的行为?我们如何摆脱它?为什么我们在 New Relic 中看不到它?


原来这是一种请求排队。有时,该网络服务器很忙,并且由于heroku只是将随机传入的请求随机路由到任何dyno,那么我可能最终会排在dyno后面的队列中,该队列由于例如以下原因而完全卡住了。数据库问题。奇怪的是,这在 new relic 中很难注意到(在查看图表中的资源时取消选中所有其他资源是个好主意,然后队列突然出现)

2013 年 2 月 21 日编辑:事实证明,它在 Newrelic 中不那么引人注目的原因是,它没有被测量!http://rapgenius.com/Lemon-money-trees-rap-genius-response-to-heroku-lyrics http://rapgenius.com/Lemon-money-trees-rap-genius-response-to-heroku-lyrics

我们发现这非常令人沮丧,最终我们放弃了 Heroku,转而使用专用服务器。这使我们以 1/10 的成本获得了 20 倍的性能提升。此外,我必须说,我们对 Heroku 感到失望,Heroku 在发生这种情况时否认缓慢是由于他们的基础设施造成的,尽管我们对此表示怀疑并多次强调了这一点。我们甚至得到了这样的答案:

Heroku 2012 年 8 月 28 日:“如果您没有在 New Relic 中看到请求排队或其他缓慢的报告,那么这可能不是服务器端问题。Heroku 的内部路由应该花费

此外,我们采访了 Newrelic,他们似乎也没有意识到这个问题,尽管他们自称与 Heroku 有着非常密切的工作关系。

新遗迹 2012 年 8 月 29 日:“看来导致这种情况的原因是在 Ruby 代理的可见性开始之前发生的。代理记录的队列时间是从请求进入测功机的时间开始的,因此速度减慢是在那之前发生的。”

最重要的是,我们最终花了很多时间来优化代码,而这并不是真正的瓶颈。另外,为了提高我们的性能,我们还使用了太高的测功机规模,但我们真正从中得到的唯一好处是从 Heroku 和 Newrelic 获得了更大的收益 - 不酷。我很高兴我们改变了。

附言。当时甚至存在一个错误,导致 newrelic pro 在所有 dynos 上收费,即使我们(根据 Newrelic 自己的建议)禁用了对后台工作进程的监控。双方花了很长时间和很多电子邮件才承认错误。

聚苯硫醚。如果您不知道当前正在进行的讨论,那么这里是链接http://rapgenius.com/James-somers-herokus-ugly-secret-lyrics http://rapgenius.com/James-somers-herokus-ugly-secret-lyrics

2013 年 2 月 26 日编辑Heroku 刚刚宣布 https://blog.heroku.com/archives/2013/2/21/better_queuing_metrics_with_updated_new_relic_add_on在他们的时事通讯中,Newrelic 发布了update http://blog.newrelic.com/2013/02/21/using-new-relic-on-heroku-read-how-our-new-ruby-agent-measures-queue-time/这显然可以让我们了解 Heroku 的情况。

2013 年 8 月 4 日编辑Heroku 刚刚发布了FAQ https://blog.heroku.com/archives/2013/4/3/routing_and_web_performance_on_heroku_a_faq超出主题

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

Heroku 上奇怪的 TTFB(第一个字节的时间)问题 的相关文章

  • 重新归档 simple_form 未定义方法 Attachment_field

    I am trying to hook up refile to my view and I am getting the following error 这是我的模型 class Job lt ActiveRecord Base acts
  • Angularjs 在生产中禁用调试数据

    我正在尝试按照角度文档中的建议禁用生产服务器中的调试数据here https docs angularjs org guide production 补充一点 我并没有真正看到性能和加载时间有任何改进 这是我的代码在 app js 中的样子
  • 为什么 .each 在我的 Rails 视图中完成后会重复数组? [复制]

    这个问题在这里已经有答案了 在我的 Rails 视图页面中 我有以下循环 它应该循环遍历我的 tag list 数组并打印每个标签 由于某种原因 它在打印每个单独的标签后会重复该数组 例如 这个数组有两个元素 ruby python 每个方
  • 在 Pandas 中创建许多新列的最 Pythonic 方法

    我有一个大数据框df 约 100 列和约 700 万行 我需要创建约 50 个新变量 列 它们是当前变量的简单转换 一种方法是与许多人一起 apply声明 我只是使用transform 作为简单转换的占位符 例如max或平方 df new
  • Rails_admin 中的范围作为过滤器

    我在我的应用程序中使用rails admin 我的模型上有一些范围 以下是一个示例 class User lt ActiveRecord Base scope unconfirmed where confirmed at IS NULL e
  • application.css 未作为资产提供

    编辑4 5和6 8小时后 欢迎任何更多的想法 也许这个错误已经被知道并解决了 但是当你在 app assets stylesheets 的 css erb 文件中有这个时 我得到了我在编辑 2 3 中描述的行为 li background
  • 为什么我的空循环在 Intel Skylake CPU 上作为函数调用时运行速度是原来的两倍?

    我正在运行一些测试来比较 C 和 Java 并遇到了一些有趣的事情 在 main 调用的函数中 而不是在 main 本身中 运行具有优化级别 1 O1 的完全相同的基准代码 导致性能大约翻倍 我正在打印 test t 的大小 以毫无疑问地验
  • 为什么在排序输入上插入到树中比随机输入更快?

    现在我一直听说从随机选择的数据构建二叉搜索树比有序数据更快 这仅仅是因为有序数据需要显式重新平衡以将树高度保持在最低限度 最近我实现了一个不可变的treap http en wikipedia org wiki Treap 一种特殊的二叉搜
  • 使用 RSpec 请求规范授权请求时,access_token 无效

    我正在尝试测试CredentialsController 使用 RSpec 请求规范在生产中运行良好 Code 控制器 class CredentialsController lt ApplicationController before
  • 快速 log2(float x) 实现 C++

    我需要在 C 中非常快速地实现 log2 float x 函数 我发现了一个非常有趣的实现 而且速度非常快 include
  • 如何将openId与rails 3中的设备集成

    我是 Rails 新手 刚刚完成了一个简单的设计设置 我正在寻求实现一些仍然使用核心设计功能集但允许通过 openid 提供商登录而不是 使用电子邮件或用户名注册 的东西 我如何开始使用最新的设计宝石和rails 3 看看devise op
  • 捆绑包 - 从另一台电脑复制粘贴宝石

    我正在尝试设置 Rails 应用程序 该应用程序依赖于大量的宝石 宝石已预先安装在vendor gems我从朋友那里获得的副本的文件夹 现在 考虑到那些闭源宝石的不可用性 bundle install path home umang pro
  • 如何使用回形针对多页 pdf 进行缩略图

    我想让 Paperclip 为上传的多页 PDF 文件的每一页创建 2 个缩略图 我正在运行 Paperclip 2 3 1 1 并在我的资产模型中使用它 has attached file asset styles gt medium g
  • Rails 4 - 将地址保存为数据库中的一列

    我是 Rails 新手 正在开发一个简单的应用程序 我的 ERD 中有一个名为 Client 的模型 并且希望保存每个客户的地址 我最初的想法是将地址保存为单独的字段 即 rails g model Client address first
  • 为什么 Haskell 的默认字符串实现是一个字符链接列表?

    Haskell 默认值的事实String众所周知 实现在速度和内存方面都效率不高 据我所知 lists一般来说 在 Haskell 中实现为单链表 并且适用于大多数小型 简单数据类型 例如Int 这似乎不是一个好主意 但是对于String这
  • Watir 脚本偶尔返回 Net::ReadTimeout 错误

    我有一个 Watir 脚本 偶尔会意外地返回此错误 Net ReadTimeout 我搜索了这个错误并发现这个问题 https stackoverflow com questions 47452276 watir get sometimes
  • 为什么我的原生 C++ 代码在 Android 上运行速度比 Java 慢很多?

    我将 Java 代码的某些部分移植到 C 以加快 Android 上的计算速度 这是一个物理子例程 我发现本机代码的运行速度比 Java 代码慢几倍 我认为我的项目配置可能有问题 或者可能是数组处理有问题 所以我在 HelloAndroid
  • 将嵌套循环计算转换为 Numpy 以加速

    我的Python程序的一部分包含以下代码段 其中一个新的网格 是根据旧网格中找到的数据计算的 网格是二维浮点数列表 该代码使用了三个 for 循环 for t in xrange 0 t step for h in xrange 1 hei
  • 为什么 Orchard 在执行内容项查询时如此慢?

    假设我想查询所有 Orchard 用户 ID 并且还想包括那些已被删除 也称为软删除 的用户 该数据库包含大约 1000 个用户 Option A 大约需要 2 分钟 Orchard ContentManagement IContentMa
  • 如何在 RoR 中实施成就系统

    我正在尝试在我的 Ruby on Rails 应用程序中实现一个成就系统 但效果很差 我有一长串想要检查的成就 所有这些都是由各种控制器中的某些创建操作触发的 我的想法是我将拥有一个成就模型 其中包括控制器及其响应的操作 然后对创建进行之前

随机推荐