1

我正在使用 Ruby Grape 创建 API,但遇到以下问题。当有新的 GET 请求时,请求的数据量很大,耗时较长,同时 Reactor 被阻塞,直到请求完成后才能处理新的请求。代码非常简单:

class API < Grape::API
  resource :users do
    get do
      get_users()
    end
  end
end

get_users 通过 TCP 连接到另一个系统,并获取大量转换为 JSON 的数据。这是使用 3rd 方 gem 完成的。处理这种情况的最佳选择是什么?

4

2 回答 2

0

您的应用程序执行长时间运行的阻塞 I/O 操作。为了很好地处理这些类型的工作负载,您的系统需要支持高 I/O 并发。

传统的单线程多进程系统,如 Phusion Passenger 开源和 Unicorn 不适合这类工作负载。它们可以处理的并发量受进程数量的限制。这个问题记录在 Unicorn 的哲学页面,“Just Worse in Some Cases”部分,或者最近关于调整 Phusion Passenger 的并发性的 Phusion 文章中。

虽然 Thin 由于其事件 I/O 模型,理论上能够处理高 I/O 并发,但必须明确编写应用程序和框架才能利用这一点。很少有框架能做到这一点。Rails 和 Sinatra 都不支持事件 I/O。Cramp 支持它,还有另一个新的事件框架,我忘记了它的名字。但似乎 Grape 不支持事件 I/O。

解决方案是切换到支持多线程的应用程序服务器,它也能够支持高 I/O 并发。一个这样的应用服务器是Phusion Passenger 4 Enterprise,它支持混合多线程/多进程模型。多线程是并发,而多进程是为了稳定性和利用多个 CPU 内核的能力。Phusion 博客描述了不同工作负载的最佳并发设置。

于 2013-03-14T11:12:36.033 回答
0

我想到了两个选择:

  1. 设置乘客/独角兽等有足够的工人来处理并发请求。
  2. 如果这还不够:重新制定 API 逻辑,以便长时间操作将分解为两个调用:第一个 - 留下请求,第二个 - 检查完成/检索结果。

此外,如果合适的话 - 您可以缓存 get_users() 的结果

于 2013-03-11T19:28:02.837 回答