5

更新:

如果您有同样的问题,请阅读“指示延迟作业已完成的 ajax 进程”。谢谢吉恩。_


我有并发问题。我有一个控制器抓取几个网站,但每次调用我的控制器需要大约 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

不管是什么控制器.rb

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

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

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

要求:

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

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

  • Heroku 与独角兽
  • Engineyard Cloud 与 Nginx + Panssenger
4

5 回答 5

4

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

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

这里有几个。

薄的

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

独角兽

Unicorn 使用一个主进程将请求分派给网络工作者,4 个工作者等于 4 个并发可能的请求。

彪马

Puma 是一个相对较新的 ruby​​ 服务器,它的亮点是它在线程中处理并发请求,确保你的代码是线程安全的!

乘客

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

其他

这些是一些替代品,还有很多其他的,但我认为它们是当今最常用的。

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

于 2014-02-18T20:37:56.367 回答
2

上面的答案是解决方案的一部分:您需要一个服务器环境,可以正确地将并发请求分派给单独的工作人员;独角兽或乘客都可以通过在单独的进程或线程中创建工作人员来工作。这允许许多工作人员在不阻塞其他传入请求的情况下坐下来等待。

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

您需要提供更多详细信息,说明您需要做什么才能帮助您找到更具体的解决方案。

于 2014-02-26T05:52:54.687 回答
2

对于任何长响应时间的控制器功能,gemdelayed job都是 不错的选择。虽然它通常用于批量邮寄,但它也适用于任何长时间运行的任务。

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

文章中没有提到的是可以使用redis或者其他一些内存缓存来存储结果而不是主库。

于 2014-02-26T10:13:20.927 回答
1

你用的是什么红宝石版本?

红宝石和网络服务器

红宝石

如果它是一个简单的应用程序,我会推荐以下。尝试使用 rubinius (rbx) 或 jruby,因为它们更擅长并发。虽然它们有缺点,因为它们不是主线 ruby​​,所以一些扩展将不起作用。但如果它是一个简单的应用程序,你应该没问题。

网络服务器

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

如果您的应用正在访问 API 服务

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

如果您是提供数据的人

但是,阅读您的问题听起来您的控制器是 API,并且锁定是由用户点击它引起的。

如果是这种情况,您应该使用 dalli + memcached 来提供数据。这样您就不会受到 SQL 查找的 I/O 限制,因为 memcached 是基于内存的。内存速度 > I/O 速度

于 2014-02-27T01:23:46.080 回答
1

尝试像独角兽这样的东西,因为它通过工人处理并发。如果每个请求有很多工作要做,那么需要考虑的其他事情是为每个请求启动一个延迟作业。

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

但是,您可以让延迟作业将其响应保存到数据库中的表中。然后,您可以查询该表以获取所有请求及其相关响应。

于 2014-02-25T16:51:14.480 回答