如何与Rails 4同时处理请求?

Fre*_*rik 32 ruby concurrency ruby-on-rails puma

我试图服务于多个请求,同时在轨道4,这是我能够用做得很轻松config.threadsafe!,并Puma在Rails 3中.

说我有这个控制器

class ConcurrentController < ApplicationController
  def index
    sleep 10000
  end

  def show
  end
end
Run Code Online (Sandbox Code Playgroud)

我以前能够开始使用puma puma -t 2:16 -p 3000(最少2个线程)然后点击index然后show仍然可以show正确渲染.

在Rails 4中,如果我尝试做同样的事情,Puma现在会锁定index请求并且show永远不会被渲染.当我点击Ctrl-C服务器时,Puma给了我这个错误:

Rack app error: #<ThreadError: Attempt to unlock a mutex which is locked by another thread>
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么来获得并发使用Rails 4?config.threadsafe!应该是不需要的(即使我尝试也没有区别)

Ely*_*Ely 36

我邀请您阅读config.threadsafe!本文中删除config.threadsafe的配置选项! 它将帮助您更好地理解选项config.threadsafe!,特别是允许并发.

在Rails 4 config.threadsafe!中默认设置.


现在回答

在Rails 4中,默认情况下,DEV环境中的Rack :: Lock中间件将请求包含在Mutex中.

如果要启用并发,可以设置config.allow_concurrency=true.这将禁用Rack :: Lock中间件.我不会删除你在问题的另一个答案中提到的; 这看起来像是对我的黑客攻击.

注意:如果您有(Rack :: Lock请求互斥锁)config.cache_classes=true的分配config.allow_concurrency将不会生效,默认情况下允许并发请求.如果有 config.cache_classes=false,则可以设置 config.allow_concurrencytruefalse.在DEV环境中,您可能想要这样

config.cache_classes=false
config.allow_concurrency=true
Run Code Online (Sandbox Code Playgroud)

声明:这意味着如果config.cache_classes = false(默认情况下在dev env中),我们就不能有并发请求.是不正确的.

附录

您可以参考这个答案,该答案设置了一个使用MRI和JRuby测试并发性的实验.结果令人惊讶.MRI比JRuby快.

MRI并发的实验在GitHub上.该实验仅测试并发请求.控制器中没有竞争条件.但是,我认为从上面的文章中实现示例来测试控制器中的竞争条件并不太困难.


Fre*_*rik 21

似乎默认情况下,在Rails 4中,并未在开发环境中启用并发请求.

我在文档中找到了这个引用.

Rack :: Lock将应用程序包装在互斥锁中,因此一次只能由一个线程调用.仅在config.cache_classes为false时启用.

这意味着如果config.cache_classes = false(默认情况下,它在dev env中)我们不能有并发请求.

并发请求可以在生产环境中使用我的示例.

一种解决方案是config.cache_classes = true在开发环境中设置,但是代码不会在更改时重新加载,这对于开发而言并不真正有用.

第二种hacky解决方案是禁用Rack::Lock开发中的中间件.

因此,如果您要添加development.rb以下行:

config.middleware.delete Rack::Lock
Run Code Online (Sandbox Code Playgroud)

你应该能够在开发环境中的并发请求禁用缓存类.