请求外部服务 (S3) 花费太多时间

Request to External Service (S3) takes too much time

我已经为此苦苦挣扎了 2 天,我只是想不出我应该做什么。我正在使用 Rails (4.2.3) 和 Ruby 2.2.1,如果有任何帮助的话。

安装新遗物后 gem 我发现我的两个控制器需要很长时间才能响应(~17 秒)的原因是对 amazon s3 的请求。

那些页面仅显示 10 条记录使用 ransack gem。

这里有截图给大家看。

任何帮助将不胜感激...

New Relic external services screenshot

像 S3 这样的外部服务调用可能需要时间,具体取决于多个变量,例如:

  1. 网络路由 b/w 您的服务器到 S3。检查 traceroute
  2. 延迟 b/w 服务器。 ping 越高,建立连接的时间越长。
  3. AWS S3 端的健康 - 如果他们的服务遇到问题,您的服务可能会受到影响
  4. 等..

通常建议在后台执行 image/file resize/upload 等任务。 Resque, Sidekiq 之类的 Gem 正是用来做到这一点的。

很难准确地说,有 10 条记录,每条记录 1.7 秒似乎相当大,也许你应该在 Rails 之外测量它(例如,直接在浏览器中请求相同的 URL)。

但通常在控制器中发出 10 个顺序请求是一件坏事。即使请求相当快,发出 10 个请求也可能是该响应中最慢的请求的很多倍。

  1. 您可以通过每个生成 10 个线程来获取记录,然后加入并呈现视图来完成此操作。
  2. 或者您可以异步获取每条记录(非阻塞,因此所有 10 条记录同时发生)。
  3. 或者,如果您可以在页面中呈现具有 AJAX/XHR 响应的数据,请让控制器仅获取 1 个项目并让应用程序单独请求所有 10 个(但您将达到浏览器对域的最大请求限制所以不会得到完整的 10 倍加速。
  4. 如果浏览器不需要立即响应,请使用后台任务运行程序(许多 Gems)并告诉浏览器 "its pending"。这将避免阻止您的 Rails 服务器,但从单个用户的角度来看甚至可能 更慢

不幸的是,Ruby/Rails 中的异步支持不是很好(猜测需要更多的人提出要求和贡献)。我认为 AWS SDK 根本不可能使用选项 2,您需要四处寻找真正异步的 HTTP 客户端库才能在低级别执行此操作(而不仅仅是 thread/fibre 包装器)。