Sinatra 和 Phusion Passenger 中的线程行为
我有一个简单的 Sinatra 应用程序通过 Phusion Passenger 在 Apache 之上运行。
当应用程序启动时,我启动一个 Ruby 线程,该线程每分钟执行一次繁重的计算,将结果保留在全局变量中(然后在其他地方访问)。
使用rackup时,变量会按预期每分钟更新和刷新一次,但是在Passenger下运行时,它似乎不会这样做。
# Seed the initial license data - on Sinatra starting - and
# set it on a global variable.
$license_data = generate_license_data(360)
# Start up a worker thread that will update the license data
# every 60 seconds. This thread will run until termination
# of the parent thread. Only this thread will modify the values
# of the global variable "license_data".
worker_thread = Thread.new do
while true
sleep 60
t = Time.now
print "Generating license data ..."
$license_data = generate_license_data(360)
print " OK (#{seconds_to_string(Time.now-t)})\n"
end
end
# Generate the actual HTML snippet we need for the license entry
# by accessing the global variable "license_data".
def generate_license_entry
# The license block.
@licensechart = {}
@licensechart[:values] = $license_data[:values_string]
# Generate the table entry.
haml :license
end
有什么想法吗?我也很高兴知道另一种更好的缓存计算的方法,以及如何每分钟更新一次。
I have a simple Sinatra app running on top of Apache via Phusion Passenger.
When the app starts, I initiate a Ruby thread that does a heavy computation once a minute, leaving the result in a global variable (which is then accessed else where).
The variable is updated and refreshed once a minute as expected when using rackup
, however when run under Passenger, it does not seem to do this.
# Seed the initial license data - on Sinatra starting - and
# set it on a global variable.
$license_data = generate_license_data(360)
# Start up a worker thread that will update the license data
# every 60 seconds. This thread will run until termination
# of the parent thread. Only this thread will modify the values
# of the global variable "license_data".
worker_thread = Thread.new do
while true
sleep 60
t = Time.now
print "Generating license data ..."
$license_data = generate_license_data(360)
print " OK (#{seconds_to_string(Time.now-t)})\n"
end
end
# Generate the actual HTML snippet we need for the license entry
# by accessing the global variable "license_data".
def generate_license_entry
# The license block.
@licensechart = {}
@licensechart[:values] = $license_data[:values_string]
# Generate the table entry.
haml :license
end
Any ideas? I'll also be happy to know of an alternate, better way of caching a computation, and how to update it once a minute.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据您对乘客的配置方式,它可能会运行多个进程(因此您将在每个进程中重复计算工作),或者没有进程(因为它可以关闭一段时间内未处理请求的实例)。
使用另一个系统来运行后台任务(例如 Resque 或 Delayed_job)会更加可靠,并且允许您根据 Web 请求需求来配置 Passenger,而与工作线程要求无关。
Depending on how you have passenger configured, it may have more than one process running (so you'd be duplicating the calculation work in each process), or none (as it can shut down instances that have not served requests for some time).
Using another system to run background tasks (like Resque or delayed_job) would be much more reliable, and allow you to configure Passenger according to your web request needs independently of your worked thread requirements.
我不太喜欢 Passenger,但我认为它正在产生多个用于提供响应的进程,因此可能无法更新和/或访问变量。保存和访问数据库中的数据至少应该可以解决这个问题。对于这种情况,我个人会选择 Resque 和 Resque Scheduler,这是一个用于创建和处理(重复)后台作业的库,这就是您现在使用线程所做的事情。
再次强调,乘客的声明具有很强的推测性,可能是错误的。
最好的问候
托比亚斯
I'm not quite into Passenger, but I think it's spawning several processes for serving responses and therefore might not be able to update and or access the variable. Saving and accessing the data in a database should at least fix that problem. For that scenario I personally would go with Resque with Resque Scheduler, which is a library for creating and processing (recurring) background jobs, which is what you do right now with a thread.
And again, the Passenger statement is highly speculative and might be wrong.
Best regards
Tobias