Ruby on rails 机架中间件与线程安全
我的Rails 4应用程序使用了一个定制的机架中间件。如果客户端没有提供有效的信息(我正在使用API),中间件本身就是默认的Ruby on rails 机架中间件与线程安全,ruby-on-rails,ruby,thread-safety,rack,puma,Ruby On Rails,Ruby,Thread Safety,Rack,Puma,我的Rails 4应用程序使用了一个定制的机架中间件。如果客户端没有提供有效的信息(我正在使用API),中间件本身就是默认的Accept和Content-Type头文件到application/json。因此,在每个请求之前,它会更改这些头,在每个请求之后,它会添加一个带有自定义媒体类型信息的自定义X-Something-Media-Type头 我想切换到Puma,因此我有点担心这样一个中间件的线程安全性。除了在每个中间件中遇到的常见@app.call之外,我没有使用实例变量,但即使在这里,我也
Accept
和Content-Type
头文件到application/json
。因此,在每个请求之前,它会更改这些头,在每个请求之后,它会添加一个带有自定义媒体类型信息的自定义X-Something-Media-Type头
我想切换到Puma,因此我有点担心这样一个中间件的线程安全性。除了在每个中间件中遇到的常见@app.call
之外,我没有使用实例变量,但即使在这里,我也复制了我在RailsCasts评论中读到的内容:
def initialize(app)
@app = app
end
def call(env)
dup._call(env)
end
def _call(env)
...
status, headers, response = @app.call(env)
...
为了处理线程安全问题,dup.\u调用
真的有用吗
除了@app
实例变量之外,我只使用当前env变量生成的当前请求:
request = Rack::Request.new(env)
我调用env.update
来更新标题和表单信息
当我从Webrick
切换到并发web服务器(如Puma
)时,期待中间件出现一些问题是否足够危险
如果是的话,您知道一些方法来隔离我的中间件中非线程安全的部分吗
谢谢。是的,必须
dup
中间件才是线程安全的。这样,您在\u call
中设置的任何实例变量都将在被复制的实例上设置,而不是在原始实例上设置。您会注意到,围绕机架构建的web框架是这样工作的:
单元测试的一种方法是断言
\u call
是在被复制的实例上而不是在原始实例上调用的。作为推论,如果不设置/更新实例变量,则不必在中间件上调用dup
。或者,使用线程安全的数据结构,例如并发ruby的缓存映射,用于共享缓存。从这里可以找到一个很好的解释: