Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц.
Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно.
Константы, которые могут влиять на запуск агентов и отправку писем:
BX_CRONTAB
BX_CRONTAB_SUPPORT
NO_AGENT_CHECK
DisableEventsCheck
Опции модуля main, которые влияют на запуск агентов:
agents_use_crontab - по умолчанию не задана
check_agents - по умолчанию не задана
При этом не всё можно прочитать в исходном коде. Файл ядра Битрикса /bitrix/modules/main/include.php обфусцирован.
Нам надо повесить все агенты на крон.
Была подобная статья и учебный курс, но там есть фатальный недостаток: все почтовые события тоже вешаются на крон. Крон работает с минимальной частотой раз в минуту. Получается, что пользователь нажимает «восстановить пароль» и минуту ждет письмо. Еще один недостаток — статья устарела и в ней нет, как настроить резервное копирование по расписанию.
Нам надо, чтобы отправка писем была на хитах, а все агенты и резервное копирование работали на кроне.
Посмотрим, как сейчас обстоят дела в Битриксе:
По умолчанию на кроне вызывается файл /bitrix/modules/main/tools/cron_events.php:
В файле в самом начале стоит define("BX_CRONTAB", true);. Из-за этого в прологе устанавливается другая константа define("BX_CRONTAB_SUPPORT", true);. В результате данный крон-скрипт обрабатывает ТОЛЬКО непериодические агенты.
Исходный код функции обработки агентов.
function CheckAgents()
{
...
//For a while agents will execute only on primary cluster group
if((defined("NO_AGENT_CHECK") && NO_AGENT_CHECK===true) || (defined("BX_CLUSTER_GROUP") && BX_CLUSTER_GROUP !== 1))
return null;
$agents_use_crontab = COption::GetOptionString("main", "agents_use_crontab", "N");
$str_crontab = "";
if($agents_use_crontab=="Y" || (defined("BX_CRONTAB_SUPPORT") && BX_CRONTAB_SUPPORT===true))
{
if(defined("BX_CRONTAB") && BX_CRONTAB===true)
$str_crontab = " AND IS_PERIOD='N' ";
else
$str_crontab = " AND IS_PERIOD='Y' ";
}
...
return CAgent::ExecuteAgents($str_crontab);
}
Настройка агентов на кроне:
Проверьте, чтобы в файле dbconn.php не было установленных констант:
BX_CRONTAB
BX_CRONTAB_SUPPORT
NO_AGENT_CHECK
DisableEventsCheck
Установите опцию, которая запрещает выполнение агента в прологе:
COption::SetOptionString("main", "check_agents", "N");
echo COption::GetOptionString("main", "check_agents", "Y"); // должно вывестись N
Опция, которая влияет на выбор агентов в функции CheckAgents, должна быть не определена или "N".
COption::SetOptionString("main", "agents_use_crontab", "N");
echo COption::GetOptionString("main", "agents_use_crontab", "N"); // должно вывестись N
<?php
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS",true);
define('BX_NO_ACCELERATOR_RESET', true); // чтобы не глючило на VMBitrix 3.1 из-за Zend при отправке бэкапа в облако.
// здесь никакой агент не выполнится. Потому что мы сделали COption::SetOptionString("main", "check_agents", "N");
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
@set_time_limit(0);
@ignore_user_abort(true);
CAgent::CheckAgents(); // а вот тут все агенты выполнятся. И периодические, и непериодические
CEvent::CheckEvents(); // почтовые события мы оставили выполняться на хитах. Но и тут они могут выполняться. Почему нет?
define("BX_CRONTAB", true);
// модуль email-маркетинг
if(CModule::IncludeModule('sender'))
{
\Bitrix\Sender\MailingManager::checkPeriod(false);
\Bitrix\Sender\MailingManager::checkSend();
}
// а еще есть файлик резервного копирования, который запустится, когда его время придет.
require($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/tools/backup.php");
?>
Пропишите правило в крон, например * * * * * /usr/bin/php -f /home/bitrix/www/bitrix/php_interface/cron_events.php
Результат
Теперь должно работать. Все агенты периодические и непериодические запускаются на cron. Все почтовые события отправляются на хитах пользователей сразу. Если к отправке письма привязана отправка SMS, то SMS тоже отправится сразу и не будет ждать крона.
Недостатки
Решение вполне рабочее, но есть проблемы:
1. Свой файл /bitrix/php_interface/cron_events.php, как и в старой статье, не будет обновляться.
Битрикс уже добавлял в крон резервное копирование по расписанию. Если они еще что-то добавят, то у вас не появится новый функционал.
2. В Виртуальной машине Битрикса уже настроен крон для файла /bitrix/modules/main/tools/cron_events.php. Вам придется настроить крон на свой файл /bitrix/php_interface/cron_events.php
Решение
Мы написали свой модуль «Агенты на кроне», который очень прост, удобен и лишен этих недостатков.
Здравствуйте. Дорабатывал кое-какой функционал и мне необходимо было отправить почту, делал это функцией mail, по не знанию метода send. Задержка была равно приветствую со стороны почтового сервера внутри сети, порядка 17 секунд. Позже открыл для себя метод Send и проблема решилась, но перед этим я где-то напортачил... Сейчас смотрю бизнес процессы, в них присутствует та самая задержка, если у меня улетают куда-либо почтовые сообщения, такое ощущение что они отправляются стандартной функцией mail, а не API - Send. Никак не могу вспомнить и понять, где накосячил и как это дело можно исправить. Помнится что читал этот блог, а так же http://dev.1c-bitrix.ru/community/web...?commen... Не могу понять какие именно настройки отвечают за то, находится ли почта на кроне, либо на хитах. В общем мне необходимо сделать как было по умолчанию, потому как обновление страницы 17 секунд, никуда не лезет.
Зайцев Артемий написал: Исходный код функции обработки агентов.
Добрый день! Вопрос: Агент который запускает функцию из init.php выполняется как изолированный процесс и его время исполнения(как php скрипта) накладывается на остальные агенты которые запускают другие функции из init.php? Т.е допустим есть 10 агентов, каждый агент это отдельная трудоёмкая функция с запросами к БД из init.php, так вот если эти агенты выполняются вместе в одну еденицу времени, те фукнции которые они запускают создают общее время выполнения скрипта путём суммы времени выполнения по отдельности или это не зависымые процессы? Можно ведь с большим количесвтвом агентов уперется в ограничение сервера на время исполнения скрипта, или я не так понимаю агентов? Агенты упомянутые тут, по условию исполняются только на кроне с интервало 120 секунд - бесконечное количество раз.
Дмитрий Балабайкин, посмотрите исходный код CAgent::CheckAgents и CAgent::ExecuteAgents.
Допустим большой агент начнет работать на хите. Приходит другой пользователь, вызывает агенты, большой агент работает, поэтому пользователь вызывает следующие агенты.
Большие агенты паралелятся по хитам пользователей.
С кроном тоже самое. Только крон вызывается раз в минуту. Если агент работает дольше минуты, то следующий агент запускается другим кроном через минуту после начала предыдущего.
Еще агенты могут выполняться через форк, если определить недокументированную константу BX_FORK_AGENTS_AND_EVENTS_FUNCTION
Артемий Зайцев, Спасибо за ответ. Соответсвенно если cron вызывается раз в пять минут, и в этом промежутке сработают несколько трудоёмких агентов, то можно и попасть на лимит исполнения скрипта? При работе агентов через форк, это не создаст ошибок с базой?
Артемий Зайцев, а надо это потому что во 2 экзамене у нас есть строчка: "(!) Функция агента работает верно, выполняясь и на хитах и на cron". То есть как я понял, мы стандартными средствами php закидываем файл на крон, а стандартную обработку агентов на хитах не меняем?
Дмитрий Помаскин, это означает, что вы должны написать агента так, чтобы он правильно выполнился на хитах (если агенты на хитах) и на кроне (если агенты на кроне).
На хитах проверить его просто. Обновите страницу несколько раз.
Если на хитах работает, то и на кроне заработает. Только имейте ввиду: на кроне другой массив $_SERVER. И определение текущей страницы будет другим.
Как на кроне проверить в условиях экзамена не очень представляю.
Можно как-то попытаться вызвать в консоли что-то вроде:
Подскажите пожалуйста в чем может быть ошибка. Запускаю команду вручную, получаю: Fatal error: Class 'CEvent' not found in /var/www/bitrix01/bitrix/modules/main/tools/cron_events.php on line 15
Подскажите пожалуйста в чем может быть ошибка. Запускаю команду вручную, получаю: Fatal error: Class 'CEvent' not found in /var/www/bitrix01/bitrix/modules/main/tools/cron_events.php on line 15
Невозможная ситуация это стандартный файл. Можете даже удалить наш модуль, чтобы убедиться что ошибка не в нем.
У меня файл /bitrix/modules/main/tools/cron_events.php выглядит так:
Проверьте, как выглядит ваш файл крона. Может быть у вас где-то криво настроены символические ссылки и не все подключается. Запустите тест битрикса по проверке модифицированных файлов ядра. (монитор качества внедрения, тест "Ядро продукта не модифицировалось")
Максименко Олег, спасибо большое! short_open_tag стоит в On и все равно не срабатывало. Помог запуск в таком виде /usr/bin/php -d display_errors -d short_open_tag /var/www/bitrix/modules/main/tools/cron_events.php
Максименко Олег, спасибо большое! short_open_tag стоит в On и все равно не срабатывало. Помог запуск в таком виде /usr/bin/php -d display_errors -d short_open_tag /var/www/bitrix/modules/main/tools/cron_events.php
Юрий Авдеев, настройки для крона не могут быть заданы в файлах .htaccess и httpd.conf. Настройки для крона должны быть указаны в php.ini и других ini-файлах которые участвуют при запуске php из консоли.
Поэтому проверьте на всякий случай, где у вас задаются настройки для PHP. Возможно, правильнее будет их перенести в php.ini.
Статья хорошая но для тех у кого при запуксе cron events из консоли для проверки выдает PHP Fatal error: require(): Failed opening required '/bitrix/modules/main/include/prolog_before.php' Необходимо в переменной убрать пробел в пути между точками вон видите в самом конце. - $_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./..");
В этой теме Алексей Шафранский (Администратор) пишет, что инструкция по переводу всех агентов на крон в документации устарела и вполне достаточно настроек по умолчанию (bitrix-env) для выполнения всех агентов на кроне.
Петин Артём, в виртуальной машине крон включается из меню по SSH, прописывать в /etc/crontab больше не надо.
Чтобы агенты на кроне заработали установщик сайта (restore.php или bitrixsetup) сам зачем-то записывает BX_CRONTAB_SUPPORT в dbconn. Так у вас на кроне будут работать непереиодические агенты и отправка писем.
Именно так, а периодические на хитах. Но он утверждает, что все агенты, а не только непериодические. Это-то и вызвало вопрос.
Значит всё ещё актуальна необходимость установки вашего модуля или ручного изменения параметров check_agents / agents_use_crontab и добавления своего крон-скрипта?
В той статье, кстати, крон-скрипт обновили в марте этого года. Не подскажете, какой из скриптов оптимальнее использовать: из той статьи или из вашей?
terseto, установите модуль на тестовый сайт https://labs.1c-bitrix.ru/ а потом скопируйте /bitrix/modules/askaron.agents к себе. Модуль бесплатный. DisableEventsCheck не трогайте, она отключает отправку писем.
Потом установите define("BX_CRONTAB_SUPPORT", true); в dbconn.php
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».