gpt4 book ai didi

ruby - 单线程还处理并发请求?

转载 作者:数据小太阳 更新时间:2023-10-29 08:04:04 25 4
gpt4 key购买 nike

Ruby 进程是单线程的。当我们使用瘦服务器启动单进程时,为什么我们仍然能够处理并发请求?

require 'sinatra'
require 'thin'
set :server, %w[thin]

get '/test' do
sleep 2 <----
"success"
end

thin里面有什么可以处理并发请求的?如果是event-machine framework的原因,上面的代码实际上是一个sync代码,不是EM使用的。

最佳答案

引用章节:"Non blocking IOs/Reactor pattern" in http://merbist.com/2011/02/22/concurrency-in-ruby-explained/ :“这是 Twisted、EventMachine 和 Node.js 使用的方法。Ruby 开发人员可以使用 EventMachine 或基于 EventMachine 的 Web 服务器,如 Thin 以及 EM 客户端/驱动程序,用于进行非阻塞异步调用。”

事情的核心是EventMachine.defer * 用于将阻塞操作集成到 EventMachine 的控制流中。 defer 的 Action 是采用第一个参数(“操作”)中指定的 block 并安排它在 EventMachine 维护的内部线程池上异步执行。

当操作完成时,它将传递 block 计算的结果(如果有的话) 回到 EventMachine react 堆。 然后,EventMachine 调用第二个参数中指定的 block 来延迟(“回调”), 作为其正常事件处理循环的一部分。

操作 block 计算的结果作为参数传递给回调。 如果操作完成后不需要执行任何代码,则可以省略回调参数。 *

本质上,为了响应 HTTP 请求,服务器会执行您编写的内容,调用 Connecticction 类中的 process 方法。查看 $GEM_HOME/gems/thin-1.6.2/lib/thin/connection.rb 中的代码:

# Connection between the server and client.
# This class is instanciated by EventMachine on each new connection
# that is opened.
class Connection < EventMachine::Connection
# Called when all data was received and the request
# is ready to be processed.
def process
if threaded?
@request.threaded = true
EventMachine.defer(method(:pre_process), method(:post_process))
else
@request.threaded = false
post_process(pre_process)
end
end

..这是线程连接调用 EventMachine.defer

的地方

react 堆

要查看激活 EventMachine reactor 的位置应该遵循程序的初始化:请注意,对于所有 Sinatra 应用程序和中间件 ($GEM_HOME/gems/sinatra-1.4.5/base.rb)可以使用 Thin、Puma、Mongrel 或 WEBrick 将 Sinatra 应用程序作为自托管服务器运行。

  def run!(options = {}, &block)
return if running?
set options
handler = detect_rack_handler
....

detect_rack_handler 方法返回第一个 Rack::Handler

 return Rack::Handler.get(server_name.to_s)

在我们的测试中,我们需要 thin 因此它返回一个 Thin 机架处理程序并设置一个线程服务器

  # Starts the server by running the Rack Handler.
def start_server(handler, server_settings, handler_name)
handler.run(self, server_settings) do |server|
....
server.threaded = settings.threaded if server.respond_to? :threaded=

$GEM_HOME/gems/thin-1.6.2/lib/thin/server.rb

# Start the server and listen for connections.
def start
raise ArgumentError, 'app required' unless @app

log_info "Thin web server (v#{VERSION::STRING} codename #{VERSION::CODENAME})"
...
log_info "Listening on #{@backend}, CTRL+C to stop"

@backend.start { setup_signals if @setup_signals }
end

$GEM_HOME/gems/thin-1.6.2/lib/thin/backends/base.rb

  # Start the backend and connect it.
def start
@stopping = false
starter = proc do
connect
yield if block_given?
@running = true
end

# Allow for early run up of eventmachine.
if EventMachine.reactor_running?
starter.call
else
@started_reactor = true
EventMachine.run(&starter)
end
end

关于ruby - 单线程还处理并发请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25450769/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com