Rails: Запланированное задание на разогрев кеша?
Я использую следующее для кэширования медленной загрузки страницы с использованием memcached:
caches_action :complex_report, :expires_in => 1.day
Действие контроллера защищено аутентификацией Devise.
В данный момент страница кэшируется при первом обращении пользователя. Последующий запрос в тот же день вытащил из кеша.
Проблема в том, что первоначальный запрос загружается за 20-30 секунд. Можно ли заполнить кеш заранее по расписанию?
Любые предложения высоко ценится.
4 ответа
Вот расширение предыдущего решения на основе cron, которое использует возможность curl для хранения файлов cookie, чтобы вы могли выполнить аутентификацию за один шаг, а затем снова использовать файл cookie в качестве аутентифицированного пользователя на следующем этапе. Так что если вы поместите эти строки в сценарий с именем "prepare_cache.sh"
rm /tmp/cookiejar
curl --request POST -d "login=<username>" -d "password=<password>" -c /tmp/cookiejar http://yourwebpages.url/login
curl --request GET -b -c /tmp/cookiejar http://yourwebpages.url/page_to_cache
rm /tmp/cookiejar
заменив параметры логина и пароля на те, которые соответствуют переменным, используемым в вашей форме входа, и, очевидно, URL-адресам для вызова. Я удаляю cookiejar прежде, чтобы убедиться, что там уже нет файла, и удаляю его в конце, чтобы убедиться, что нет cookie, плавающего с уровнями доступа, которых он не должен иметь.
Затем вы можете вызвать этот скрипт с помощью задания cron:
*/15 * * * * /home/myname/prepare_cache.sh > /dev/null 2>&1
И, надеюсь, это должно сработать. Казалось, работает на меня, когда я попробовал это.
Посмотрите на этот драгоценный камень:
https://github.com/tommyh/preheat
Драгоценный камень предназначен для подогрева вашего Rails.cache.
Из документации:This will "preheat" all your Rails.cache.fetch calls on your homepage. It is as simple as that!
#app/models/product.rb
def slow_method
Rails.cache.fetch("product-slow-method-#{self.id}") do
sleep 15
Time.now
end
end
#lib/tasks/preheat.rake
namespace :preheat do
desc "Preheat product caches"
task (:products => :environment) do
Preheat.it do
Product.all.each do |product|
app.get(app.products_path(product)) #or you could just call product.slow_method directly, whatever makes more sense
end
end
end
end
#crontab -e
0 * * * * /path/to/rake preheat:products RAILS_ENV=production 2>&1 >> #{Rails.root}/log/preheat.log &
Если это процесс запуска отчета и сбора результатов, который отнимает много времени, вы можете кэшировать эти результаты (вместо кэширования действий или параллельно), используя Rails.cache.write
а также Rails.cache.read
,
Тогда, поскольку вам не нужно беспокоиться об аутентификации или отправке запросов на сервер, процесс выполнения запроса и кэширования результатов из задания cron будет значительно проще.
Вероятно, самым основным решением было бы создать простую cron
запись, чтобы загрузить страницу, вы хотите иметь "горячий" кэш. Это может быть так просто добавить следующее к crontab
пользователя на вашем сервере с помощью crontab -e
открыть редактор:
*/15 * * * * wget -q http://yourwebpages.url/ > /dev/null 2>&1
Что это будет делать, это использовать wget
получать данные по указанному URL каждые 15 минут каждого часа, дня, месяца и года, игнорировать результаты и не отправлять *nix почту в случае, если что-то пойдет не так.