【问题标题】:Rack middleware and thread-safety机架中间件和线程安全
【发布时间】:2014-05-26 12:46:00
【问题描述】:

我的 Rails 4 应用程序使用了一个自定义机架中间件。如果客户端未提供有效信息(我正在处理 API),则中间件本身只是默认 AcceptContent-Type 标头为 application/json。因此,在每个请求之前,它都会更改这些标头,并在每个请求之后添加一个带有自定义媒体类型信息的自定义 X-Something-Media-Type 头。

我想切换到 Puma,因此我有点担心这种中间件的线程安全性。我没有使用实例变量,除了我们在每个中间件中遇到的常见 @app.call 一次,但即使在这里我也复制了我在 RailsCasts 的 cmets 中读到的一些内容:

def initialize(app)
 @app = app
end

def call(env)
 dup._call(env)
end

def _call(env)
 ...
 status, headers, response = @app.call(env)
 ...

dup._call 对于处理线程安全问题真的有用吗?

除了@app 实例变量我只玩用当前环境变量构建的当前请求:

request      = Rack::Request.new(env)

我打电话给env.update 来更新标题和表单信息。

当我从 Webrick 切换到并发 Web 服务器(例如 Puma)时,预期该中间件会出现问题是否足够危险?

如果是,您是否知道一些方法来进行一些测试以隔离我的中间件的非线程安全部分?

谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby thread-safety rack puma


    【解决方案1】:

    是的,dup 中间件必须是线程安全的。这样,您从_call 设置的任何实例变量都将设置在被复制的实例上,而不是原始实例上。您会注意到围绕 Rack 构建的 Web 框架是这样工作的:

    对此进行单元测试的一种方法是断言 _call 是在一个被欺骗的实例而不是原始实例上调用的。

    【讨论】:

    • 作为推论,如果您不设置/更新实例变量,则无需在中间件上调用dup。或者,使用线程安全的数据结构,例如concurrent-ruby 的缓存映射,用于共享缓存。
    • 从这里找到了一个很好的解释:crypt.codemancers.com/posts/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 2013-01-31
    相关资源
    最近更新 更多