gpt4 book ai didi

ruby - 瘦异步应用程序示例如何缓冲对主体的响应?

转载 作者:太空宇宙 更新时间:2023-11-03 16:07:10 25 4
gpt4 key购买 nike

您好,我一直在阅读关于 Thin 的文档,我对 eventmachine 还比较陌生,但我知道 Deferrables 是如何工作的。我的目标是了解当 body 被逐部分延迟和流式传输时,Thin 是如何工作的。

以下是我正在使用并试图理解的示例。


class DeferrableBody
include EventMachine::Deferrable

def call(body)
body.each do |chunk|
@body_callback.call(chunk)
end

# @body_callback.call()
end

def each &blk
@body_callback = blk
end

end

class AsyncApp

# This is a template async response. N.B. Can't use string for body on 1.9
AsyncResponse = [-1, {}, []].freeze
puts "Aysnc testing #{AsyncResponse.inspect}"

def call(env)

body = DeferrableBody.new

# Get the headers out there asap, let the client know we're alive...
EventMachine::next_tick do
puts "Next tick running....."
env['async.callback'].call [200, {'Content-Type' => 'text/plain'}, body]
end

# Semi-emulate a long db request, instead of a timer, in reality we'd be
# waiting for the response data. Whilst this happens, other connections
# can be serviced.
# This could be any callback based thing though, a deferrable waiting on
# IO data, a db request, an http request, an smtp send, whatever.
EventMachine::add_timer(2) do
puts "Timer started.."
body.call ["Woah, async!\n"]

EventMachine::add_timer(5) {
# This could actually happen any time, you could spawn off to new
# threads, pause as a good looking lady walks by, whatever.
# Just shows off how we can defer chunks of data in the body, you can
# even call this many times.
body.call ["Cheers then!"]
puts "Succeed Called."
body.succeed
}
end

# throw :async # Still works for supporting non-async frameworks...
puts "Async REsponse sent."
AsyncResponse # May end up in Rack :-)
end

end

# The additions to env for async.connection and async.callback absolutely
# destroy the speed of the request if Lint is doing it's checks on env.
# It is also important to note that an async response will not pass through
# any further middleware, as the async response notification has been passed
# right up to the webserver, and the callback goes directly there too.
# Middleware could possibly catch :async, and also provide a different
# async.connection and async.callback.

# use Rack::Lint
run AsyncApp.new

我不太清楚的部分是 DeferrableBody 类在 calleach 方法中发生了什么。

我知道,一旦计时器作为存储在@body_callback 中的 block 触发,每个都会收到数据 block ,当在主体上调用成功时,它会发送主体,但何时是 yieldcall 在这些 block 上调用它如何在发送时变成单个消息。

我觉得我对闭包的了解还不足以理解发生了什么。对此有任何帮助将不胜感激。

谢谢。

最佳答案

好吧,我想我弄清楚了每个 block 的工作原理。

Thin on post_init 似乎在连接进入时生成一个 @request@response 对象。响应对象需要响应到 each 方法。这是我们覆盖的方法。

env['async.callback'] 是一个闭包,分配给 connection.rb 类中名为 post_process 的方法数据实际发送到连接的方法,如下所示


@response.each do |chunk|
trace { chunk }
puts "-- [THIN] sending data #{chunk} ---"
send_data chunk
end

如何定义响应对象的 each


def each
yield head

if @body.is_a?(String)
yield @body
else

@body.each { |chunk| yield chunk }
end
end

所以我们的 env['async.callback'] 基本上是一个名为 post_process 的方法,定义在通过 method(:post_process) 访问的 connection.rb 类中,允许我们的方法像闭包一样处理,它包含对@response 对象的访问。当 reactor 启动时,它首先在 next_tick 中发送 header 数据,并在其中产生 head,但此时 body 是空的,因此不会产生任何东西。

在此之后,我们的 each 方法覆盖了 @response 对象拥有的旧实现,因此当 add_timers 触发 post_process 被触发将我们使用 body.call(["Wooah..."]) 提供的数据发送到浏览器(或任何地方)

完全敬畏 macournoyer 和致力于瘦身的团队。如果您觉得这不是它的工作原理,请纠正我的理解。

关于ruby - 瘦异步应用程序示例如何缓冲对主体的响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11245872/

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