Как лучше всего запускать запланированные задачи в среде Rails? Скрипт / бегун? Грабли? Я хочу запускать задачу каждые несколько минут.
Cron для рельсов: лучшие практики?
Ответы (20)
Я использую метод рейка (поддерживаемый heroku)
С файлом lib / tasks / cron.rake ..
task :cron => :environment do
puts "Pulling new requests..."
EdiListener.process_new_messages
puts "done."
end
Для выполнения из командной строки это просто rake cron. Затем эту команду можно поместить в планировщик cron / задач операционной системы по желанию.
Обновление, это довольно старый вопрос и ответ! Немного новой информации:
- Служба heroku cron, на которую я ссылался, с тех пор заменена Heroku Scheduler
- для частых задач (особенно, когда вы хотите избежать затрат на запуск среды Rails), я предпочитаю использовать системный cron для вызова сценария, который либо (а) запускает безопасный / частный API веб-перехватчика, чтобы вызвать требуемую задачу в фоновом режиме или (б) напрямую поставить задачу в очередь в выбранной вами системе очередей.
load "#{Rails.root}/lib/tasks/cron.rake"
и rake cron
, но получил NameError: undefined локальную переменную или метод cron для main: Object
- person B Seven; 22.07.2011
:environment
. У нас есть очень тяжелое приложение Rails, которое долго запускается, наш Rake вызывается каждую минуту и потребляет больше ресурсов, запуская среду Rails, которая выполняет задачу. Я бы хотел иметь уже запущенную среду Rails для вызова через cron, должно быть что-то среднее между подходом controller и средой rake я> один.
- person fguillen; 17.01.2012
Я использовал чрезвычайно популярный всякий раз в проектах, которые сильно зависят от запланированных задач, и это здорово. Это дает вам хороший DSL для определения ваших запланированных задач вместо того, чтобы иметь дело с форматом crontab. Из README:
Anywhere - это драгоценный камень Ruby, который обеспечивает четкий синтаксис для написания и развертывания заданий cron.
Пример из README:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end
В нашем проекте мы сначала использовали всякий раз gem, но столкнулись с некоторыми проблемами.
Затем мы перешли на гем RUFUS SCHEDULER, который оказался очень простой и надежный для планирования задач в Rails.
Мы использовали его для отправки еженедельных и ежедневных писем и даже для выполнения некоторых периодических рейк-задач или любого другого метода.
Используемый здесь код выглядит так:
require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new
scheduler.in '10d' do
# do something in 10 days
end
scheduler.at '2030/12/12 23:30:00' do
# do something at a given point in time
end
scheduler.every '3h' do
# do something every 3 hours
end
scheduler.cron '5 0 * * *' do
# do something every day, five minutes after midnight
# (see "man 5 crontab" in your terminal)
end
Чтобы узнать больше: https://github.com/jmettraux/rufus-scheduler
Предполагая, что выполнение ваших задач не занимает много времени, просто создайте новый контроллер с действием для каждой задачи. Реализуйте логику задачи в виде кода контроллера. Затем настройте задание cron на уровне ОС, которое использует wget для вызова URL-адреса этого контроллера и действия через соответствующие промежутки времени. Преимущества этого метода в том, что вы:
- Получите полный доступ ко всем вашим объектам Rails, как в обычном контроллере.
- Может развиваться и тестироваться так же, как вы делаете обычные действия.
- Также может вызывать ваши задачи adhoc с простой веб-страницы.
- Не потребляйте больше памяти, запуская дополнительные процессы ruby / rails.
Проблема с when (и cron) заключается в том, что он перезагружает среду rails каждый раз, когда выполняется, что является реальной проблемой, когда ваши задачи часто выполняются или требуют большой работы по инициализации. Из-за этого у меня возникли проблемы в производстве, и я должен вас предупредить.
Планировщик Rufus сделает это за меня (https://github.com/jmettraux/rufus-scheduler)
Когда мне нужно выполнить долгую работу, я использую ее с delayed_job (https://github.com/collectiveidea/delayed_job)
Надеюсь, это поможет!
Задачи script / runner и rake отлично подходят для выполнения как задач cron.
Вот одна очень важная вещь, которую вы должны помнить при запуске заданий cron. Вероятно, они не будут вызываться из корневого каталога вашего приложения. Это означает, что все ваши требования к файлам (в отличие от библиотек) должны выполняться с явным путем: например. Имя_файла (__ FILE__) + "/ другой_файл". Это также означает, что вы должны знать, как явно вызывать их из другого каталога :-)
Проверьте, поддерживает ли ваш код запуск из другого каталога с помощью
# from ~
/path/to/ruby /path/to/app/script/runner -e development "MyClass.class_method"
/path/to/ruby /path/to/rake -f /path/to/app/Rakefile rake:task RAILS_ENV=development
Кроме того, задания cron, вероятно, не запускаются от вашего имени, поэтому не полагайтесь на какой-либо ярлык, который вы добавили в .bashrc. Но это всего лишь стандартный совет cron ;-)
Я большой поклонник resque / планировщик восстановления. Вы можете запускать не только повторяющиеся задачи, похожие на cron, но и задачи в определенное время. Обратной стороной является то, что для этого требуется сервер Redis.
Интересно, что никто не упомянул Sidetiq. Это приятное дополнение, если вы уже используете Sidekiq.
Sidetiq предоставляет простой API для определения повторяющихся воркеров для Sidekiq.
Работа будет выглядеть так:
class MyWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { hourly.minute_of_hour(15, 45) }
def perform
# do stuff ...
end
end
Оба будут работать нормально. Я обычно использую скрипт / раннер.
Вот пример:
0 6 * * * cd /var/www/apps/your_app/current; ./script/runner --environment production 'EmailSubscription.send_email_subscriptions' >> /var/www/apps/your_app/shared/log/send_email_subscriptions.log 2>&1
Вы также можете написать сценарий на чистом Ruby, чтобы сделать это, если вы загрузите правильные файлы конфигурации для подключения к своей базе данных.
Одна вещь, о которой следует помнить, если память важна, - это то, что скрипт / бегун (или задача Rake, которая зависит от «среды») загрузит всю среду Rails. Если вам нужно только вставить несколько записей в базу данных, это будет использовать память, в которой вам действительно не нужно. Если вы напишете свой собственный сценарий, вы можете избежать этого. На самом деле мне это еще не требовалось, но я обдумываю это.
Используйте Craken (задания cron, ориентированные на грабли)
Я использую backgroundrb.
http://backgroundrb.rubyforge.org/
Я использую его для выполнения запланированных задач, а также задач, которые занимают слишком много времени для нормальных отношений клиент / сервер.
Использование чего-то Sidekiq или Resque - гораздо более надежное решение. Оба они поддерживают повторные попытки выполнения заданий, эксклюзивность с блокировкой REDIS, мониторинг и планирование.
Имейте в виду, что Resque - мертвый проект (активно не поддерживается), поэтому Sidekiq - лучшая альтернатива. Он также более производительный: Sidekiq запускает несколько рабочих процессов в одном многопоточном процессе, в то время как Resque запускает каждого рабочего в отдельном процессе.
Вот как я настроил свои задачи cron. У меня есть один, чтобы делать ежедневные резервные копии базы данных SQL (с использованием граблей), а другой - для истечения срока действия кеша один раз в месяц. Любой вывод записывается в файл log / cron_log. Мой crontab выглядит так:
crontab -l # command to print all cron tasks
crontab -e # command to edit/add cron tasks
# Contents of crontab
0 1 * * * cd /home/lenart/izziv. whiskas.si/current; /bin/sh cron_tasks >> log/cron_log 2>&1
0 0 1 * * cd /home/lenart/izziv.whiskas.si/current; /usr/bin/env /usr/local/bin/ruby script/runner -e production lib/monthly_cron.rb >> log/cron_log 2>&1
Первая задача cron делает ежедневные резервные копии БД. Содержимое cron_tasks следующее:
/usr/local/bin/rake db:backup RAILS_ENV=production; date; echo "END OF OUTPUT ----";
Вторая задача была настроена позже и использует скрипт / бегун для истечения срока действия кеша один раз в месяц (lib / month_cron.rb):
#!/usr/local/bin/ruby
# Expire challenge cache
Challenge.force_expire_cache
puts "Expired cache for Challenges (Challenge.force_expire_cache) #{Time.now}"
Думаю, я мог бы сделать резервную копию базы данных другим способом, но пока это работает для меня :)
Пути к рейку и рубину могут отличаться на разных серверах. Вы можете увидеть, где они находятся, используя:
whereis ruby # -> ruby: /usr/local/bin/ruby
whereis rake # -> rake: /usr/local/bin/rake
Недавно я создал несколько рабочих мест cron для проектов, над которыми работаю.
Я обнаружил, что драгоценный камень Clockwork очень полезен.
require 'clockwork'
module Clockwork
every(10.seconds, 'frequent.job')
end
Вы даже можете запланировать свою фоновую работу с помощью этого драгоценного камня. Для документации и дополнительной помощи см. https://github.com/Rykian/clockwork.
вы можете использовать resque
и resque-schedular
gem для создания cron, это очень просто сделать.
https://github.com/resque/resque
https://github.com/resque/resque-scheduler
Когда-то мне пришлось принять такое же решение, и я очень доволен этим решением сегодня. Используйте resque scheduler, потому что не только отдельный redis снимает нагрузку с вашей базы данных, у вас также будет доступ ко многим плагинам, таким как resque-web, который обеспечивает отличный пользовательский интерфейс. По мере развития вашей системы у вас будет появляться все больше и больше задач для планирования, поэтому вы сможете управлять ими из одного места.
Вероятно, лучший способ сделать это - использовать грабли для написания необходимых вам задач и просто выполнить их через командную строку.
Вы можете посмотреть очень полезное видео на железнодорожных трансляциях
Также взгляните на эти другие ресурсы:
Я использовал гем часовой механизм, и он мне очень подходит. Также есть clockworkd
драгоценный камень, который позволяет скрипту запускаться как демон.
Я не совсем уверен, думаю, это зависит от задачи: как часто запускать, насколько сложно и сколько нужно прямого взаимодействия с проектом rails и т. Д. Думаю, если бы был только "One Best Way" , чтобы что-то сделать, не было бы так много разных способов сделать это.
На моей последней работе в проекте Rails нам нужно было создать пакетную рассылку приглашений (приглашения на опрос, а не рассылку спама), которая должна отправлять запланированные письма всякий раз, когда у сервера есть время. Я думаю, мы собирались использовать инструменты демона для выполнения созданных мною задач с граблями.
К сожалению, у нашей компании были проблемы с деньгами, и она была «куплена» основным конкурентом, поэтому проект так и не был завершен, поэтому я не знаю, что бы мы в конечном итоге использовали.
Я использую скрипт для запуска cron, это лучший способ запустить cron. Вот пример для cron,
Откройте CronTab -> sudo crontab -e
И вставьте линии сильфона:
00 00 * * * wget https://your_host/some_API_end_point
Вот какой формат cron поможет вам
::CRON FORMAT::
Examples Of crontab Entries
15 6 2 1 * /home/melissa/backup.sh
Run the shell script /home/melissa/backup.sh on January 2 at 6:15 A.M.
15 06 02 Jan * /home/melissa/backup.sh
Same as the above entry. Zeroes can be added at the beginning of a number for legibility, without changing their value.
0 9-18 * * * /home/carl/hourly-archive.sh
Run /home/carl/hourly-archive.sh every hour, on the hour, from 9 A.M. through 6 P.M., every day.
0 9,18 * * Mon /home/wendy/script.sh
Run /home/wendy/script.sh every Monday, at 9 A.M. and 6 P.M.
30 22 * * Mon,Tue,Wed,Thu,Fri /usr/local/bin/backup
Run /usr/local/bin/backup at 10:30 P.M., every weekday.
Надеюсь, что это поможет вам :)