Чтобы почта была на хитах Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц. Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно. Константы, которые могут влиять на запуск агентов и отправку писем: 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: <?php $_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./. ./. ./.."); $DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"]; define("NO_KEEP_STATISTIC", true); define("NOT_CHECK_PERMISSIONS",true); define("BX_CRONTAB", true); define('BX_NO_ACCELERATOR_RESET', true); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php"); @set_time_limit(0); @ignore_user_abort(true); CEvent::CheckEvents(); require($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/tools/backup.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 Свой крон-скрипт: Создайте файл /bitrix/php_interface/cron_events.php: <?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(); // почтовые события мы оставили выполняться на хитах. Но и тут они могут выполняться. Почему нет? // а еще есть файлик резервного копирования, который запустится, когда его время придет. // в принципе необязательно. В версии 14.0.0 появилась возможность запускать резервное копирование из облака. Облако Битрикса само приходит и делает бэкап define("BX_CRONTAB", true); 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 тоже отправится сразу и не будет ждать крона.
Компания АКРИТ
Выполнение всех агентов на cron.
Чтобы почта была на хитах
Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц.
Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно.
Константы, которые могут влиять на запуск агентов и отправку писем:
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:
<?php
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./. ./. ./..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS",true);
define("BX_CRONTAB", true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
@set_time_limit(0);
@ignore_user_abort(true);
CEvent::CheckEvents();
require($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/tools/backup.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
Свой крон-скрипт:
Создайте файл /bitrix/php_interface/cron_events.php:
<?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(); // почтовые события мы оставили выполняться на хитах. Но и тут они могут выполняться. Почему нет?
// а еще есть файлик резервного копирования, который запустится, когда его время придет.
// в принципе необязательно. В версии 14.0.0 появилась возможность запускать резервное копирование из облака. Облако Битрикса само приходит и делает бэкап
define("BX_CRONTAB", true);
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 тоже отправится сразу и не будет ждать крона.