我刚刚在我的新项目代码库中看到过像这样的独角兽服务器配置:
worker_processes ENV['UNICORN_WORKERS'].to_i || 2
preload_app true
timeout 30
after_fork do |server, worker|
Thread.new do
begin
RABBIT_CONNECTION = Bunny.new(ENV['AMQP_URL'])
RABBIT_CONNECTION.start
rescue Bunny::TCPConnectionFailed => e
puts "Connection failed"
end
begin
OUTGOING_CHANNEL = RABBIT_CONNECTION.create_channel
rescue Bunny::PreconditionFailed => e
puts "Channel-level exception! Code: #{e.channel_close.reply_code},
message: #{e.channel_close.reply_text}".squish
ensure
RABBIT_CONNECTION.close
end
end
end
据我所知,独角兽是一个单线程,多进程的Web服务器。
这个Thread.do
块有什么作用?如果所有其他代码都没有被Thread.do
块包围,会发生什么?
答案 0 :(得分:3)
是的unicorn是一个单线程,多进程的Web服务器。这里,Thread.do被用于使用Bunny客户端异步连接到RabbitMQ。也就是说,unicorn在创建进程后不会等待RabbitMQ连接。线程会等待同样的。
在Unicorn(或MRI ruby)中,一次只能有一个线程使用CPU。这是通过使用称为GIL或全局解释器锁的东西来完成的。
阅读本文:http://www.jstorimer.com/blogs/workingwithcode/8085491-nobody-understands-the-gil
而且:https://en.wikipedia.org/wiki/Global_interpreter_lock
但是,对于等待连接到RabbitMQ服务器的IO操作,此线程不会耗尽CPU周期,其他线程可以在CPU上运行。
如果没有Thread.do,并且RabbitMQ服务器无法访问,则进程将等待服务器可用或连接超时。