Ruby 单线程仍然处理并发请求?

Ruby 单线程仍然处理并发请求?,ruby,multithreading,thin,Ruby,Multithreading,Thin,Ruby进程是单线程的。当我们使用瘦服务器启动单个进程时,为什么我们仍然能够处理并发请求 require 'sinatra' require 'thin' set :server, %w[thin] get '/test' do sleep 2 <---- "success" end 需要“sinatra” 需要“瘦” 设置:服务器%w[精简] 获取“/test”do 睡眠2引用章节:中的“非阻塞IOs/反应器模式” : 这是Twisted、EventMachine和Nod

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

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

get '/test' do
  sleep 2   <----
  "success"
end
需要“sinatra”
需要“瘦”
设置:服务器%w[精简]
获取“/test”do

睡眠2引用章节:中的“非阻塞IOs/反应器模式” : 这是Twisted、EventMachine和Node.js使用的方法。Ruby开发人员可以使用EventMachine或Node.js 基于EventMachine的Web服务器,如Thin和EM客户端/驱动程序,用于进行非阻塞异步调用。”

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

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

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

本质上,为了响应HTTP请求,服务器执行您编写的, 调用connection类中的
进程
方法。 查看
$GEM\u HOME/gems/thin-1.6.2/lib/thin/connection.rb中的代码

服务器和客户端之间的连接。 #该类由EventMachine在每个新连接上实例化 #那是打开的。 类连接
#在收到所有数据和请求时调用
#已准备好进行处理。
def过程
如果有螺纹?
@request.threaded=true
延迟(方法(:预处理),方法(:后处理))
其他的
@request.threaded=false
后处理(前处理)
结束
结束
…这里是线程连接调用EventMachine.defer的地方

反应堆 查看在何处激活了 应遵循程序的初始化步骤: 请注意,对于所有Sinatra应用程序和中间件(
$GEM\u HOME/gems/Sinatra-1.4.5/base.rb
) 可以使用Thin、Puma、Mongrel或WEBrick作为自托管服务器运行Sinatra应用程序。

方法detect\u rack\u handler返回第一个rack::handler

return Rack::Handler.get(server\u name.to\s)
在我们的测试中,我们需要thin,因此它返回一个瘦机架处理程序并设置一个线程服务器

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

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


Ruby不是单线程。嗨@Franco,回答是thx。所以在我看来,异步只是在HTTP连接上,当运行ruby代码时,它仍然是同步的,对吗?基本上是的。除了我的回答之外,搜索更多文档可能会有所帮助,例如,当您有时间时,您可以观看演示文稿,如:本演示文稿,如果发现有不清楚的地方,还可以搜索具体问题
  def run!(options = {}, &block)
    return if running?
    set options
    handler         = detect_rack_handler
  ....
  # 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=
# 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
  # 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