Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц.
Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно.
Константы, которые могут влиять на запуск агентов и отправку писем:
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
Решение
Мы написали свой модуль «Агенты на кроне», который очень прост, удобен и лишен этих недостатков.
Артемий Зайцев, на первый взгляд, Вы переключили выполнение на другую ветку ( " AND IS_PERIOD='Y' " ), и теперь крон-скрипт обрабатывает только _периодические_ агенты (плюс backup.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 закидываем файл на крон, а стандартную обработку агентов на хитах не меняем?
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».