13

我有一个 ruby​​ on rails 应用程序,我试图找到一种每隔几秒钟运行一些代码的方法。

我发现很多使用 cron 或类似 cron 的实现的信息和想法,但这些只是精确到分钟,和/或需要外部工具。我想每 15 秒左右启动一次任务,并且我希望它完全独立地包含在应用程序中(如果应用程序停止,任务停止,并且没有外部设置)。

这用于缓存数据的后台生成。每隔几秒钟,该任务将组装一些数据,然后将其存储在缓存中,供所有客户端请求使用。该任务非常慢,因此它需要在后台运行并且不阻塞客户端请求。

我对 ruby​​ 很陌生,但是有很强的 perl 背景,我解决这个问题的方法是创建一个间隔计时器和处理程序,它分叉、运行代码,然后在完成后退出。
仅仅模拟一个客户端请求并让 Rails 控制器自己派生可能会更好。这样,我可以通过点击它的 URI 来启动任务(尽管由于任务将每隔几秒运行一次,我怀疑我是否需要这样做,但可能会在未来使用)。尽管让控制器调用周期性任务调度程序正在调用的任何方法(一旦我有一个)是微不足道的。

4

7 回答 7

13

我建议无论何时 gem https://github.com/javan/whenever

它允许您指定一个时间表,例如:

every 15.minutes do
  MyClass.do_stuff
end

没有安排 cron 作业或使用外部服务进行监控。

于 2012-11-13T01:10:48.163 回答
2

一般来说,我所知道的在应用程序中创建周期性任务的内置方式是不存在的。Rails 建立在 Rack 之上,它期望接收 http 请求,做一些事情,然后返回。所以你只需要自己在外部管理周期性任务。

我认为考虑到运行任务所需的频率,一个不错的解决方案可能只是为自己编写一个永远循环的简单 rake 任务,并在启动应用程序的同时启动它,使用像 Foreman 之类的东西。Foreman 经常像这样用于管理启动/关闭后台工作人员及其应用程序。在生产环境中,您可能希望使用其他东西来管理流程,例如 Monit。

于 2012-11-13T03:27:07.057 回答
2

您可以编写自己的方法,例如

class MyWorker
  def self.work
    #do you work
    sleep 15
  end
end

运行它rails runner MyWorker.work 会有一个单独的进程在后台运行

或者你可以使用像 Resque 这样的东西,但这是一种不同的方法。它的工作原理是这样的:向队列中添加一个任务,同时一个工作人员正在获取队列中的任何作业,并尝试完成它。

所以这取决于你自己的需要。

于 2012-11-13T04:01:01.547 回答
2

我知道这是一个老问题。但也许对于某人来说,这个答案可能会有所帮助。有一个叫做crono的宝石。

Crono 是一个用于 Ruby on Rails 的基于时间的后台作业调度程序守护进程(就像 Cron 一样)。

Crono 是纯 Ruby。它不使用 Unix Cron 和其他平台相关的东西。因此,您可以在 Ruby 支持的所有平台上使用它。它使用 Active Record 将作业状态持久化到您的数据库中。您可以完全控制作业执行过程。它是 Ruby,因此您可以理解和修改它以满足您的需求。

crono 最棒的地方在于它的代码是自我解释的。为了定期执行任务,您可以执行以下操作:

Crono.perform(YourJob).every 2.days

也许你也可以这样做:

Crono.perform(YourJob).every 30.seconds

不管怎样,你真的可以做很多事情。另一个例子可能是:

Crono.perform(TestJob).every 1.week, on: :monday, at: "15:30"

我建议使用这个 gem 而不是无论何时,因为无论何时使用 Unix Cron 表,它并不总是可用。

于 2018-05-17T16:54:43.747 回答
1

仅仅因为它看起来有点优雅而抛出一个解决方案,并且没有任何额外的宝石就回答了这个问题。在我的场景中,我想运行一些代码,但只有在我所有的 Sidekiq 工作人员都完成了他们的工作之后。

首先我定义了一个方法来检查是否有工人在工作......

def workers_working?
  workers = Sidekiq::Workers.new.map do |_process_id, _thread_id, work|
    work
  end
  workers.size > 0
end

然后我们只需使用在调用之间休眠的循环来调用该方法。

sleep 5 while workers_working?
于 2021-09-15T20:22:50.660 回答
0

使用延迟作业之类的东西,并经常重新排队?

于 2012-11-12T23:28:31.307 回答
0

使用使用 eventmachine 的瘦服务器或其他服务器,然后只使用作为 eventmachine 一部分的计时器。示例:在 config/application.rb

EM.add_periodic_timer(2) do
  do_this_every_2_sec
end  
于 2017-05-11T07:40:49.027 回答