我有一个rails应用程序,使用MRI,红宝石和Unicorn作为应用服务器。该应用程序提供了一个为期10周的健身项目,我已经为作为管理员登录的人们建立了一个功能,使他们能够在程序中“时间旅行”到不同的周。基本上,它只是设置一个会话变量,其中包含“时间旅行”到的日期,并且,每个请求都是时间--在开始时到达那个点,然后在结束时返回。代码在下面。
我限制了非生产环境的功能,因为我担心一个人的时间旅行可能会影响其他用户(因为TimeCop猴子补丁核心类)。但是,鉴于MRI并不是真正的多线程,我现在认为这是一种非理性的恐惧,在生产中使用“时间旅行”功能不应该有危险。
在处理单个请求的持续时间内(因此,如果用户使用的是“时间旅行”,则TimeCop对核心类进行猴子修补的时间),任何其他请求都不可能在相同的ruby进程上运行。
这是正确的吗?或者其他用户的请求会以我不知道的方式受到TimeCop对核心类的更改的影响吗?
我使用的代码如下:
module TimeTravelFilters
extend ActiveSupport::Concern
included do
if Rails.env.development? || Rails.env.staging?
around_action :time_travel_for_request
end
end
def time_travel_for_request
time_travel
yield
time_travel_return
end
def time_travel
if session[:timetravel_to_date]
Timecop.travel(session[:timetravel_to_date])
end
end
def time_travel_return
Timecop.return
end
end发布于 2016-02-17 08:51:26
MRI的全局解释器锁确实意味着两个线程不会并发执行,但是它的粒度要比处理一个请求小得多。
碰巧独角兽不使用线程进行并发,所以你会没事的,但是当你切换到另一台服务器(如美洲狮)时,你会有一个令人讨厌的惊喜。
这也会影响日志中的数据、任何更新的创建_at/ updated _at时间戳等等。它也可能影响监测数据收集服务,如新文物,空气制动等,如果你使用这些服务。另一个看起来完全不相关的例子是对AWS的api请求:验证这些请求的签名包含一个时间戳,如果您不同步超过几分钟,它们就会失败。有太多的代码(其中很多是您无法控制的)假设Time.now是准确的。
最好是识别那些隐式使用当前时间的代码,并更改它们以允许将所需的时间作为参数传递。
顺便说一句,我认为如果控制器引发异常,您的代码将保留更改的时间。
https://stackoverflow.com/questions/35450367
复制相似问题