处理Unicorn + Rails应用程序中的长请求

时间:2013-01-14 15:28:53

标签: ruby-on-rails web-services node.js nginx unicorn

我们有一个Rails应用程序,我们在Unicorn(2个工作者)和nginx上运行。我们希望集成第三方API,其中单个请求的处理需要1到20秒。如果我们只是创建一个代理该服务的新控制器,整个应用程序都会受到影响,因为只需2个人就可以通过我们的API向该服务发出请求,并且20秒内其他用户无法访问其他用户应用

我们正在考虑两种解决方案。

  1. 创建一个单独的node.js服务器,该服务器将执行对第三方API的所有请求。在这种情况下,我们只会使用Rails进行身份验证/授权,我们会使用X-Accel-Redirect标头通过nginx将请求重定向到节点(如此处所述http://blog.bitbucket.org/2012/08/24/segregating-services/
  2. 用Thin或Rainbow替换Unicorn!并继续代理我们的Rails应用程序,这可能会让我们处理更多的并发连接。
  3. 哪种解决方案可能会更好?或者我们还能做些什么。

    我个人觉得节点偶数循环更适合这里的工作,因为在选项2中我们仍然会阻塞许多线程并等待HTTP请求完成,而在选项1中,我们可能会在等待时做更多请求为了缓慢完成。

    谢谢!

2 个答案:

答案 0 :(得分:1)

我们已经在生产中使用X-Accel-Redirect解决方案已经有一段时间了,而且效果很好。

在服务器下的nginx配置中,我们有外部服务的条目(在我们的例子中用node.js编写),例如。

server {
  ...
  location ^~ /some-service {
    internal;
    rewrite ^/some-service/(.*)$ /$1 break;
    proxy_pass http://location-of-some-service:5000;
  }
}

在rails中我们对请求进行身份验证和授权,当我们想将其传递给其他服务时,在控制器中我们会执行类似

的操作
headers['X-Accel-Redirect'] = '/some-service'
render :nothing => true

现在,rails已完成处理请求并将其交还给nginx。 Nginx会看到x-accel-redirect标头,并将请求重播到新网址 - /some-service,我们将其配置为代理我们的node.js服务。即使node.js + nginx仍在处理原始请求,Unicorn和rails现在也可以处理新请求。

这样我们就可以使用Rails作为我们应用程序的主要入口点和守门员 - 这就是身份验证和授权发生的地方。但是,当更合适时,我们能够将大量功能转移到这些较小的独立node.js服务中。

答案 1 :(得分:0)

您可以在现有的Rails应用中使用EventMachine,这意味着更少的重写。您可以向API发出net/http请求并添加回调,而不是向API发出EM::HttpRequest请求。这类似于node.js选项,但不需要特殊的服务器IMO。