RoR:连续多次调用同一个长时间响应控制器

时间:2014-02-18 20:25:09

标签: ruby-on-rails heroku concurrency engineyard

更新

如果遇到同样的问题,请先阅读“Indicate to an ajax process that the delayed job has completed”。谢谢Gene


我遇到并发问题。我有一个控制器抓取几个网站,但每次调用我的控制器需要大约4-5秒来响应。

因此,如果我连续呼叫2次(或更多次),则第二次呼叫需要在开始之前等待第一次呼叫。

那我怎么能在我的控制器中修复这个问题呢?也许像EventMachine这样的东西?

更新& 示例

  

application_controller.rb

def func1
    i=0
    while i<=2
        puts "func1 at: #{Time.now}"
        sleep(2)
        i=i+1
    end
end

def func2
    j=0
    while j<=2
        puts "func2 at: #{Time.now}"
        sleep(1)
        j=j+1
    end
end
  

whatever_controller.rb

puts ">>>>>>>> Started At #{Time.now}"
  func1()
  func2()
puts "End at #{Time.now}"

所以现在我需要从同一个用户/浏览器/等同时多次请求http://myawesome.app/whatever

我和Unicorn一起尝试过Heroku(和本地),但没有成功,这是我的设置:

要求:

  • 我需要一个RESTful解决方案。这是API所以我需要响应JSON

更多信息: 我现在正在运行2台云服务器。

  • Heroku with Unicorn
  • 使用Nginx + Panssenger的Engineyard Cloud

5 个答案:

答案 0 :(得分:4)

您可能在开发模式下使用webrick。 Webrick一次只处理一个请求。

您有多个解决方案,存在许多可以处理并发的ruby Web服务器。

以下是其中一些。

Thin最初基于mongrel,并使用eventmachine来处理多个并发连接。

独角兽

Unicorn使用一个主进程将请求发送给Web worker,4个worker等于4个并发可能的请求。

彪马

Puma是一个相对较新的ruby服务器,其闪亮的功能是它处理线程中的并发请求,确保您的代码是线程安全的!

乘客

Passenger是捆绑在nginx或apache中的ruby服务器,非常适合生产和开发

其他

这些是一些替代品,还存在许多其他选择,但我认为它们是今天使用最多的。

要使用所有这些服务器,请查看他们的说明。它们通常可以在他们的github README上找到。

答案 1 :(得分:2)

上述答案是解决方案的一部分:您需要一个能够将并发请求分配给单独的工作人员的服务器环境;独角兽或乘客都可以通过在不同的流程或线程中创建工作人员来工作。这允许许多工作人员坐在那里等待而不阻止其他传入请求。

如果您正在构建一个典型的机器人,其主要工作是从其他来源获取内容,这些解决方案可能没问题。但是,如果您需要的是一个可以接受数百个并发请求的简单控制器,所有这些请求都将独立请求发送到其他服务器,您将需要自己管理线程或进程。您的目标是让许多工作人员等待完成一项简单的工作,以及一个或多个主人,他们的工作是发送请求,然后在那里接收响应。 Ruby的Thread类很简单,适用于像ruby 2.x或1.9.3这样的情况。

您需要提供更多有关您需要做些什么的详细信息,以帮助您获得更具体的解决方案。

答案 2 :(得分:2)

对于任何长响应时间控制器功能, the delayed job gem 是一个很好的方式去。虽然它经常用于批量邮件发送,但它适用于任何长时间运行的任务。

您的控制器启动延迟作业并立即响应具有占位符的页面 - 通常是带有进度指示器的图形 - 以及Ajax或定时重新加载,以便在页面可用时使用完整信息更新页面。有关如何处理此问题的一些信息是in this SO article

本文中未提及您可以使用redis或其他内存缓存来存储结果而不是主数据库。

答案 3 :(得分:1)

尝试类似独角兽的东西,因为它通过工作人员处理并发。如果每个请求需要完成大量工作,还需要考虑其他事项,即根据请求启动delayed_job。

延迟作业的一个问题是响应不会同步,这意味着它不会返回用户的浏览器。

但是,您可以让延迟的作业保存对DB中表的响应。然后,您可以查询该表以查找所有请求及其相关响应。

答案 4 :(得分:1)

你使用什么ruby版本?

Ruby&amp;网络服务器

红宝石

如果它是一个简单的应用程序,我会推荐以下内容。尝试使用rubinius(rbx)或jruby,因为它们在并发性方面更好。虽然它们有缺点,因为它们不是主线红宝石,所以一些扩展不起作用。但如果它是一个简单的应用程序,你应该没事。

网络服务器

如果您有耐心设置它,请使用Puma或Unicorn

如果你的应用程序正在点击API服务

你指出全局锁定在你抓取其他网站(可能是允许抓取的网站)时会杀死你,如果是这种情况,应该使用像sidekiq或延迟工作的情况,但要小心。这些将是幂等的工作。即它们可能会多次运行。如果您多次开始访问网站,您将很快达到网站的速率限制,例如。 twitter限制您每小时150个请求。因此请谨慎使用后台作业。

如果您是提供数据的人

然而,阅读您的问题听起来像您的控制器是API,而锁是由用户点击它引起的。

如果是这种情况,您应该使用dalli + memcached来提供数据。这样,由于memcached是基于内存的,因此您不会受SQL查找的I / O限制。记忆速度&gt; I / O SPEED