【问题标题】:- Rails & cron & whenever / a few minutes delay when the server is heavily loaded- Rails & cron & 每当服务器负载过重时延迟几分钟
【发布时间】:2021-08-12 09:45:33
【问题描述】:

我使用一个名为“无论何时”的 gem 来管理我的 cron 作业。 在 cronfile 中,我有每 1 分钟调用一次任务 XXXX 的 cron 作业。我的 config/schedule.rb 是这样的:

every '* * * * *' do
  rake "XXXXXXXX"
end

此 cron 作业运行良好,稍有延迟。任务 XXXX 在进程创建几秒钟后开始运行它的第一行。由于这个任务不到 1 分钟就完成了,我不应该同时有多个进程。

但是,服务器负载很重,这个延迟会变成几分钟。
这导致许多未完成的进程保留在我的进程列表中,因为 cron 作业每分钟创建一个进程。

这会导致服务器变重,如果最坏的情况发生,服务器完全死机。

为什么会这样?如何防止 cronjob 延迟调用任务?

【问题讨论】:

  • Rake 任务并不是每分钟都运行它们,因为每次运行它们时,它们都会加载整个 Rails 环境。您应该改变您的方法并考虑将该逻辑移至后台作业并处理该逻辑以触发该作业以用于已经运行的 Rails 实例。
  • 感谢您的评论。 “Rake 任务不是每分钟都运行一次”是什么意思?
  • I have every 1 minute cron job which call a task XXXX
  • 我同意,这听起来不像是 Ruby gem 或 crontab 的问题。机器只是超载了。您可能只需将时间延长至五分钟即可消除颠簸。如果花费超过一分钟的命令是 Rails 应用程序中的 Rake 任务,那么您可能不需要在该 Rake 任务中加载 :environment,这可能有助于它更快地运行。如果这些都没有帮助,那么我同意您需要某种后台作业系统,例如 Active Job。

标签: ruby-on-rails ruby cron whenever


【解决方案1】:

您可以添加dependent task 来检查服务器是否正在运行,快速失败(也就是提前失败),例如我想在调用之前验证我的rails server 是否已经在端口3000 上启动rake :test

# Rakefile
task :check_localhost do
  pid = system("lsof -i tcp:3000 -t")
  fail unless pid # or you can use `abort('message')`
end

task :test => :check_localhost do
  puts "****** THIS IS TEST ******"
end

【讨论】:

  • 非常感谢。在我的情况下,服务器正在运行,但负载如此之大,以至于调用我的 rake 任务需要超过几分钟的时间。所以我认为我无法通过其他任务检测到它。
  • @user16012143 如何同步该 rake 任务,这样如果第一次任务运行并卡住等待繁重的服务,例如 5 分钟,那么接下来的 4 个任务(每 1 分钟发出一次)将等待直到完成第一次拍摄?
  • rake 任务如何与 Rails 服务器共享相同的进程?它们将始终是两个独立的进程。
猜你喜欢
  • 2017-12-06
  • 1970-01-01
  • 2017-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
相关资源
最近更新 更多