ela*_*ado 5 ruby-on-rails thin thread-safety unicorn
由于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
Run Code Online (Sandbox Code Playgroud)
尝试添加config.threadsafe!到application.rb,没有变化.
存储每个请求数据的正确方法是什么?
为什么有使用Thread.current进行存储的宝石(包括Rails本身和倾斜)?他们如何克服这个问题?
可能是Thread.current 对于每个请求是安全的,但是在请求之后不能清除,我需要自己做吗?
总结下面与@skalee和@JesseWolgamott的讨论以及我的发现 -
Thread.current取决于运行应用程序的服务器.虽然服务器可能确保在同一个Thread.current上没有同时运行两个请求,但是此哈希中的值可能不会在请求之间被清除,因此在使用情况下 - 必须将初始值设置为覆盖最后一个值.
有一些众所周知的宝石使用Thread.current,如Rails,倾斜和draper.我想如果它被禁止或不安全,他们就不会使用它.在使用散列上的任何键之前,它们似乎都设置了一个值(甚至在请求结束后将其设置回原始值).
但总的来说,Thread.current并不是每个请求存储的最佳实践.对于大多数情况,更好的设计会做,但在某些情况下,使用env可以帮助.它可以在控制器中使用,也可以在中间件中使用,并且可以注入应用程序中的任何位置.
更新2 - 似乎现在,draper错误地使用Thread.current.请参阅https://github.com/drapergem/draper/issues/390
更新3 - 修正了漏斗错误.
您通常希望在会话中存储内容。如果你想要一些真正短暂的东西,请参阅Rails 的 flash。每个请求都会清除它。任何依赖线程的方法在不同的网络服务器上都不会一致地工作。
另一种选择是修改env哈希值:
env['some_number'] = 5
Run Code Online (Sandbox Code Playgroud)
BTW Unicorn 不仅仅是单线程,它是分叉的。每个请求都会生成新进程(尽管听起来很可怕,但在 Linux 上非常高效)。因此,如果您在 Unicorn 中设置任何内容,即使是全局变量,它也不会持续到另一个请求。
| 归档时间: |
|
| 查看次数: |
2827 次 |
| 最近记录: |