由于 Thin/Unicorn 是单线程的,您如何处理 Thread.current/per-request 存储?
只是运行了一个简单的测试——在一个会话中设置一个键,从另一个会话中读取它——看起来它一直在同一个地方写入/读取。虽然不会在 WEBrick 上发生。
class TestController < ApplicationController
def get
render text: Thread.current[:xxx].inspect
end
def set
Thread.current[:xxx] = 1
render text: "SET to #{Thread.current[:xxx]}"
end
end
尝试添加config.threadsafe!
到 application.rb,没有变化。
存储每个请求数据的正确方法是什么?
为什么会有使用 Thread.current 进行存储的 gem(包括 Rails 本身和倾斜)?他们如何克服这个问题?
难道 Thread.current 对每个请求都是安全的,但在请求后并不清楚,我需要自己做吗?
- 用 Rails 3.2.9 测试
更新
总结下面与@skalee 和@JesseWolgamott 的讨论以及我的发现——
Thread.current 取决于运行应用程序的服务器。尽管服务器可能会确保没有两个请求在同一个 Thread.current 上同时运行,但此哈希中的值可能不会在请求之间被清除,因此在使用情况下 - 必须将初始值设置为覆盖最后一个值。
有一些著名的 gem 使用 Thread.current,比如 Rails、tilt 和 draper。我猜如果它被禁止或不安全,他们就不会使用它。似乎他们都在使用哈希上的任何键之前设置了一个值(甚至在请求结束后将其设置回原始值)。
但总的来说,Thread.current 并不是按请求存储的最佳实践。在大多数情况下,更好的设计会起作用,但在某些情况下,使用env
会有所帮助。它可以在控制器中使用,也可以在中间件中使用,并且可以注入到应用程序的任何位置。
更新 2 - 就目前而言,draper 似乎错误地使用了 Thread.current。见https://github.com/drapergem/draper/issues/390
更新 3 - 该 draper 错误已修复。