Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
446 views
in Technique[技术] by (71.8m points)

ruby - How can I serve requests concurrently with Rails 4?

I'm trying to serve multiple requests concurrently in Rails 4, something I was able to do very easily with config.threadsafe! and Puma in Rails 3.

Say I have this controller

class ConcurrentController < ApplicationController
  def index
    sleep 10000
  end

  def show
  end
end

I used to be able to just start puma with puma -t 2:16 -p 3000 (for min 2 threads) and hit index and then show and still have show render properly.

In Rails 4, if I attempt to do the same thing Puma now locks on the index request and show never gets rendered. When I hit Ctrl-C for the server Puma gives me this error:

Rack app error: #<ThreadError: Attempt to unlock a mutex which is locked by another thread>

What am I missing here to get concurrency to work with Rails 4? config.threadsafe! is supposed to not be needed (and doesn't make a difference even if I try)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I invite you to read about the configuration options of config.threadsafe! in this article Removing config.threadsafe! It will help you to understand better the options of config.threadsafe!, in particular to allow concurrency.

In Rails 4 config.threadsafe! is set by default.


Now to the answer

In Rails 4 requests are wrapped around a Mutex by the Rack::Lock middleware in DEV environments by default.

If you want to enable concurrency you can set config.allow_concurrency=true. This will disable the Rack::Lock middleware. I would not delete it as mentioned in another answer to your question; that looks like a hack to me.

Note: If you have config.cache_classes=true then an assignment to config.allow_concurrency (Rack::Lock request mutex) won't take effect, concurrent requests are allowed by default. If you have config.cache_classes=false, then you can set config.allow_concurrency to either true or false. In DEV environment you would want to have it like this

config.cache_classes=false
config.allow_concurrency=true

The statement: Which means that if config.cache_classes = false (which it is by default in dev env) we can't have concurrent requests. is not correct.

Appendix

You can refer to this answer, which sets up an experiment testing concurrency using MRI and JRuby. The results are surprising. MRI was faster than JRuby.

The experiment with MRI concurrency is on GitHub. The experiment only tests concurrent request. There are no race conditions in the controller. However, I think it is not too difficult to implement example from the article above to test race conditions in a controller.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...