我正在用 Ruby 为我的工作编写一个作业调度应用程序(主要是使用各种协议以给定的频率移动文件)
我的主循环如下所示:
while true do
# some code to launch the proper job
sleep CONFIG["interval"]
end
它的工作就像一个魅力,但我不确定它是否足够安全,因为应用程序可能在运行 cpu 密集型软件的服务器上运行。
有没有其他方法可以做同样的事情,或者sleep()
在我的情况下足够安全?
我正在用 Ruby 为我的工作编写一个作业调度应用程序(主要是使用各种协议以给定的频率移动文件)
我的主循环如下所示:
while true do
# some code to launch the proper job
sleep CONFIG["interval"]
end
它的工作就像一个魅力,但我不确定它是否足够安全,因为应用程序可能在运行 cpu 密集型软件的服务器上运行。
有没有其他方法可以做同样的事情,或者sleep()
在我的情况下足够安全?
每当我觉得需要阻塞时,我都会使用事件循环;通常是libev。这是一个 Ruby 绑定:
http://rev.rubyforge.org/rdoc/
基本上,sleep
如果您希望您的进程进入睡眠状态而不在后台进行任何其他操作,那是完全可以的。但是,如果您想做其他事情,例如睡眠并等待 TCP 连接或文件句柄变得可读,那么您将不得不使用事件循环。那么,为什么不在一开始就使用一个呢?
您的申请流程将是:
main {
Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
loop();
}
当你想做其他事情时,你只需创建观察者,它就会发生在你身上。(您正在运行的作业也可以创建观察者。)
对于快速和肮脏的事情,使用 sleep 可能是可以的。但是对于需要更多鲁棒性或可靠性的事情,我建议睡眠是邪恶的:) 睡眠的问题是线程(我在这里假设 Windows ......)真的睡着了 - 调度程序不会运行线程直到睡眠间隔过去一段时间。
在此期间,线程不会因任何事情而唤醒。这意味着它不能被取消或唤醒以处理某种事件。当然,进程可以被杀死,但这并没有给睡眠线程一个唤醒和清理任何东西的机会。
我对 Ruby 不熟悉,但我认为它具有某种等待多种事物的功能。如果可以的话,我建议您不要使用睡眠,而是等待两件事\
如果有某种事件可以用来表示需要工作,那就更好了。这将避免对计时器进行轮询。这通常会导致较低的资源利用率和响应速度更快的系统。
如果您不需要确切的间隔,那么这对我来说很有意义。如果您需要在没有漂移的情况下定期唤醒,您可能需要使用某种外部计时器。但是当你睡着时,你并没有使用 CPU 资源。昂贵的是任务切换。
虽然sleep(timeout)
非常适合某些设计,但需要牢记一个重要的警告。
SA_RESTART
Ruby 使用(参见此处)安装信号处理程序,这意味着您的sleep
(或等效的select(nil, nil, nil, timeout)
)不能轻易被中断。您的信号处理程序将触发,但程序将立即返回到sleep
. 如果您希望及时对 a 做出反应,这可能会带来不便SIGTERM
。
考虑到...
#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz. I enjoyed my nap."
...执行大约需要 30 秒,而不是 2 秒。
作为一种解决方法,您可以改为在信号处理程序中抛出异常,这会中断上面的睡眠(或其他任何事情!)。您还可以切换到select
基于 - 的循环并使用自管道技巧的变体在收到信号后“提前”唤醒。正如其他人所指出的,功能齐全的事件库也可用。
它在睡眠时不会使用 CPU,但如果你睡了很长时间,我会更担心正在运行的 ruby 解释器在它没有做任何事情时会占用内存。这没什么大不了的。