На одном из подшефных сайтов обнаружилась проблема: хуки крона не успевают отрабатывать и предыдущий процесс, запущенный из crontab, всё ещё в работе при попытке запуска очередного задания. Периодичность запуска - порядка 5 минут (это необходимо для кастомного функционала отправки различных уведомлений). Сообщение об ошибке в журнале Друпала:
Attempting to re-run cron while it is already running.
Соответственно, хуки крона в текущем запуске не отрабатывают.
Путём анализа журнала был выявлен виновник: system_cron(). По интервалу времени с вызовом следующего хука было установлено длительность его выполнения: 7-8 минут. Что, конечно, слишком много. Ранее весь пул хуков hook_cron() выполнялся за минуту-другую. Т.е. проблема относительно недавняя.
Так, к сведению: размер БД по словам заказчика порядка 20Гб. Нод около 50 000.
Как временное решение - увеличили некоторые лимиты PHP и интервал запусков crontab (до 10 минут). Проблема вроде бы стала проявлять себя реже, но порой ошибка таки возникают.
В чём может быть причина и что может быть не так с system_cron()?
UPD. Немного уточнил описание проблемы.
Комментарии
Рекомендую вынести кастомный функционал в drush функцию и дёргать её серверным кроном каждые 5 минут. Друпаловский крон при этом пусть работает раз в 1-3 часа как обычно
Друпаловский poormancron вообще отключили. Только запуски из кронтаба сервера.
Я имел в виду не использовать крон друпала для запуска кастомных задач. Пусть крон друпала занимается своими делами типа проверки обновлений и удаления старых файлов
Неважно как запускается крон друпала : через веб или через крон сервера
Понял, спасибо.
PS. другие рекомендации/идеи/предположения также приветствуются.
system_cron() делает всего две задачи - чистит таблицу flood и удаляет из таблицы file_managed и на диске временные файлы. Смотрите в этих направлениях.
Может с файловой системой что-то не так?
Тоже было смутное предположение на этот счёт. Но пока конкретных действий в этом направлении не делал - анализирую разные причины.
Кроме того, на конкретно этом сайте написан кастомный модуль для cleanup'а managed-файлов. Т.е. периодически выполняется чистка по собственным алгоритмам (удаление дубликатов и "потерянных файлов" ) и по конкретному дереву файловой структуры (кстати, самому ёмкому в плане размера). И поэтому вроде как особой нагрузки на крон в этом плане быть не должно. Но всё равно стоит проверить. Спасибо.
По-прежнему приветствуются альтернативные идеи/предположения/рекомендации.
Я бы нашел код этого систем-крона и начал закомментаривать его куски прям в ядре и смотреть что выйдет. Для начала можно его вообще отключить, чтобы прямо, а не косвенно убедиться, что дело именно в нем.
Наверное - да, имеет смысл проверить.
Спасибо.
Поставьте elysia_cron и выясните точно виновника и время его работы.
Спасибо.
Дело, в том что на продакшене подобная манипуляция требует определённой подготовки и согласования. Так же, как и предложенный выше вариант с комментированием тела хука system_cron(). Это всё можно сделать, но предварительно нужно забекапиться и обосновать клиенту необходимость этих пробных мер.
Есть и подобие dev-версии, полностью актуальной по коду и конфигурации, но уже в несколько неактуальном состоянии БД и контента. На ней такой проблемы нет. Т.е. - это проблема каких-то данных продакшена, судя по всему.
system_cron еще чистит просроченные записи из кэш таблиц в бд. Посмотрите размеры таблиц в базе, может что-то разрослось. Объем базы мне кажется великоват. 50к нод это не так много. Можно еще глянуть медленные запросы, если лог включен, может там что-то будет.
Да вот я тоже удосужился посмотреть system_cron(). Действительно, некоторая очистка кеша, expirable-значений, флуда и queues-очередей. Намёка на операции с managed-файлами не нашёл. А вот по поводу queues и батчей - тут возможно есть о чём подумать.
Предметно БД пока не исследовал, но заказчик уверяет, что такой объём преимущественно из-за кеша.
да, вот здесь как раз очищаются expired строки из таблиц cache_*
<?php
foreach (Cache::getBins() as $cache_backend) {
$cache_backend->garbageCollection();
}
?>
Это чистятся строки в таблице key_value_expire
Понятно, спасибо.
Да, я упустил этот момент, а он самый важный. Обычно очень сильно разрастается таблица кэша форм cache_form.
Еще этот крон и батчи чистит, чтоб уж полностью упомянуть все его задачи.
Всё равно спасибо.
Кстати да - у меня объем базы при таком же количестве нод в пределах 1ГБ.
Думаю, количество, состав и множественность полей тоже имеют значение. Ещё около 5000 заказов коммерца по несколько позиций в каждом. Терминов, кстати, тоже несколько тысяч. Почти все обильно филдованные
Вам надо было уточнить что речь идет о d8. С managed-файлами в кроне семерки делается зачиcтка.
Как-то упустил из виду. По привычке только тег D8 поставил.
Звучит почти невероятно, но проблема перестала себя проявлять - сама собой. После двух суток ада при каждом запуске крона - сегодня утром всё вошло в обычный режим работы.
Размер БД сократился до 6 Гб. Видимо, таки был кеш или застрявшие батчи/очереди.
И, кстати, то, что всё решилось "само собой" - как-то напрягает, поскольку точная причина осталась невыясненной. Стало быть можно ждать прецедентов.
Не мог диск просто тормозить в это время?
Я думаю - вряд ли.
Кроме того, по свежим следам выявили ещё одну закономерность: system_cron() начинает тормозить, если по крону включена генерация XML sitemap. Причём, пока не очень понятно, как это связано - учитывая то, что у xml sitemap свой крон-хук и он отрабатывает самым последним в очереди - и отрабатывает в общем-то быстро. В итоге отключили регенерацию карты сайта по крону и решили регенерировать вручную.
Генерируйте через вызов из crontab drush command соответствующей, она там есть готовая.
Спасибо, будем иметь в виду.