Битрикс рекомендует для ускорения работы сайта переносить выполнение агентов с хитов пользователей на крон.
Агенты — это служебные задачи, которые запускаются в определенное время. Например, пересчет рейтинга пользователей сайта запускается раз в час.
Агенты запускаются, когда какой-нибудь пользователь заходит на сайт. Если при посещении страницы вдруг запустился пересчет рейтингов, то страница может дольше открываться.
Разумно запускать выполнение агентов с помощью служебной программы cron, а не на хитах пользователей.
В Битриксе нет понятного инструмента для переноса агентов на крон.
Есть несколько советов и моя статья, как создать отдельный файл, как настроить крон и установить несколько непонятных констант.
Такие решения рабочие, но требуют настройки, изучения, и свой отдельный крон-файл не будет обновляться.
Мы используем стандартный файл Битрикса /bitrix/modules/main/tools/cron_events.php. Крон уже настроен в Виртуальной машине Битрикса для этого файла, и делать ничего не надо.
На других хостингах вам придется настроить правило, например: * * * * * /usr/bin/php -f /home/bitrix/www/bitrix/modules/main/tools/cron_events.php
Об этом написано в подсказке на странице настроек:
С модулем «Агенты на кроне» будут все возможности, которые появятся в Битриксе при будущих обновлениях.
Мы очень старались сделать модуль простым и понятным. Поэтому он немножко платный. Срок демо-периода 30 дней. Демо-версия полностью функциональная.
Модуль бесплатный.
UPD 25.11.2014 Частые вопросы:
— Нужно ли прописывать константу BX_CRONTAB_SUPPORT в dbconn.php?
— Нет, необязательно. С нашим модулем агенты не зависят от константы BX_CRONTAB_SUPPORT.
Но от этой константы в Битриксе зависит отправка почты.
Если вы напишите define("BX_CRONTAB_SUPPORT", true) ; в dbconn.php, то почтовые события будут срабатывать на кроне раз в минуту.
Если уберете константу, то почта будет отправляться без задержки на хитах пользователей.
— Нужно ли прописывать константу BX_CRONTAB в dbconn.php?
— Нет, ни в коем случае, забудьте про неё. Константа BX_CRONTAB уже прописана в служебном файле, который вызывается кроном. В dbconn.php для всех страниц её включать нельзя.
Пришлось подробно изучить вопрос откуда в Битриксе «неожиданно» возникают глобальные переменные. В некоторых случаях между $CODE и $_REQUEST["CODE"] нет разницы.
Странно? Почему $CODE содержит значение? Первая мысль: «настройка register_globals включена». Но на виртуальной машине и на хостинге она выключена. Тем более известно, что эта опция потенциально опасна при неправильном использовании и даже удалена в версии php 5.4.0.
После длительного исследования была найдена функция, которая вызывается при подключении заголовка /bitrix/header.php:
На странице /index.php любая используемая переменная будет глобальной. $GLOBALS или global писать не надо.
Внутри функций своё изолированное пространство имен, и к глобальной переменной можно обращаться через массив $GLOBALS или ключевое слово global.
<?// index.php
// Пример 1. Установка глобальной переменной до функции
function ShowGlobalValue()
{
echo $GLOBALS["value"];
}
$value = 1;
ShowGlobalValue(); // покажет 1
?>
<?// index.php
// Пример 2. Установка глобальной переменной внутри функции
function SetGlobalValue()
{
$GLOBALS["value"] = "1";
}
SetGlobalValue();
echo $value; // покажет 1
?>
Фрагмент функции FormDecode() делает из переменной $_GET["CODE"] глобальную переменную $CODE. Поэтому /index.php?CODE=Artemy всегда создает переменную $CODE=Artemy:
foreach($_GET as $key => $val)
if(!isset($superglobals[$key]))
$GLOBALS[$key] = $val;
Аналогично из $_SERVER["DOCUMENT_ROOT"] получается глобальная переменная $DOCUMENT_ROOT.
Выводы:
Несмотря на то, что сейчас везде PHP 5.3 и PHP 5.4, в Битриксе эмулируется register_globals=on. Это означает, что переменные перед использованием на странице надо объявлять. Иначе они могут быть неожиданно получены из URL.
Компонент вызывается функцией $APPLICATION->IncludeComponent(), значит в нем пространство имен изолировано.
Включаемый файл вызывается функцией $APPLICATION->IncludeFile(). В нем тоже пространство имен изолировано.
Настоятельно не рекомендуется писать код на странице. Пишите код внутри компонентов, или во включаемых файлах, или в функциях.
На странице можно писать короче $CODE вместо $_REQUEST["CODE"]. Но лучше $_REQUEST["CODE"], потому что такой код при копировании в другое место не вызовет странных ошибок.
Спасибо за уточнение. В bitrix:catalog и не должно работать из-за особенности компонента. Если вы используете комплексный компонент, то фильтр нужно задавать внутри шаблона компонента bitrix:catalog, после вызова компонента catalog.smart.filter, но перед catalog.section.
Мы рассмотрели, какие бывают агенты. Теперь научимся их запускать на кроне. Мы сможем переложить часть задач с пользователей сайта на крон и ускорить время выполнения страниц.
Признаюсь. К этому снаряду я подходил несколько раз. И только с последнего толчка смог осилить этот вес. Сложность в том, что существует большое количество недокументированных констант и опций. Их совместное поведение совершенно не очевидно.
Константы, которые могут влиять на запуск агентов и отправку писем:
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
Решение
Мы написали свой модуль «Агенты на кроне», который очень прост, удобен и лишен этих недостатков.
Именно так, а периодические на хитах. Но он утверждает, что все агенты, а не только непериодические. Это-то и вызвало вопрос.
Значит всё ещё актуальна необходимость установки вашего модуля или ручного изменения параметров check_agents / agents_use_crontab и добавления своего крон-скрипта?
В той статье, кстати, крон-скрипт обновили в марте этого года. Не подскажете, какой из скриптов оптимальнее использовать: из той статьи или из вашей?
Практически все наши проекты — магазины с интеграцией. Решение проблем с интеграцией занимает значительную часть нашего времени на этапе внедрения и при технической поддержке.
Мы собрали наши наработки в один мощный инструмент «Продвинутый обмен с 1С» для решения различных задач:
ускорение обмена
отладка
отказоусточивость.
некоторых других.
Ускорение. Выгрузка только цен и остатков
Клиентам надо очень часто обновлять остатки и цены. Описания товаров выгружать надо редко.
Выгрузка изменений не всегда помогает. Иногда надо делать полную.
На одном проекте на большой базе полная выгрузка шла 32 часа. Пока она шла, остатки были неактуальны. При этом остатки и цены записывались на последнем шаге за 6 минут.
Как ускорить обмен?
Включаем в модуле «Продвинутый обмен с 1С» флажок «Загружать только цены и остатки (файл с описанием товаров будет пропущен)».
В 1С картинки и файлы можно отключить.
Делаем обмен.
Получаем полную выгрузку цен и остатков за 30 минут: 20 минут 1С формирует файлы + 4 минуты передача данных + 6 минут запись на сайте.
В документации описан еще один пример. Можно настроить не один обмен, а два. Первый — полный, второй — только цены и остатки.
Ускорение. Быстрая запись свойств товаров
Все-таки полную выгрузку товаров надо хоть иногда делать. 32 часа — очень много. Все эти 32 часа остатки и цены неактуальны.
Включаем опцию «Быстрая запись свойств товаров».
Получили полную выгрузку за 16 часов вместо 32. Это приемлимо. Значит за ночь можно все обновить.
Опция записывает только используемые свойства. Если в инфоблоке всего 1000 свойств, а у товара только 20, значит остальные 980 пустых проверяются и пишутся вхолостую.
Вот так двумя галочками можно решить бизнес-задачи с медленным обменом. Дальше надо думать, как оптимизировать сервер или оптимизировать код в 1С.
Отладка. Живой лог
Клиент хочет видеть, как идет обмен, и, как долго еще ждать. Особенно актуально для Управления торговлей 11, которая не показывает, что происходит.
Живой лог в реальном времени показывает, что сейчас происходит:
Страничка обновляется мгновенно с помощью модуля Push and Pull. Можно «откинуться на спинку кресла» и смотреть, как идет обмен, с 1С.
Модуль Push and Pull есть в Малом Бизнесе.
Отладка. Лог-файл
Программистам нужно больше информации. Например, о том, сколько времени записывается товар, и, на каком товаре произошел сбой.
Для этого есть инструмент — лог-файл. Включите флажок «Записывать все шаги в лог-файл».
В лог-файле будет то, что 1С собирается записать на сайт и время шагов.
Отказоустойчивость:
Отказоустойчивость — не менее важная характеристика обмена, чем скорость.
Для заказчика очень неприятна ситуация, когда обмен шел несколько часов и из-за чего-то прервался. Для разработчика самая страшная ситуация, когда такой заказчик звонит и требует разобраться почему прервался обмен. Вина может быть не в разработчике, а в сервере, но заказчик все-равно будет звонить разработчику
Мы уменьшаем нагрузку на сервер, отключаем лишнее и выставляем правильные параметры для Битрикса и PHP.
1. Мы сохраняем время последнего обмена, чтобы знать когда обновились цены в каталоге.
2. Иногда надо корректно прервать обмен или полностью запретить для переноса сайта.
Заключение:
Настройка обмена и техподдержка — задача нетривиальная. Не на всех сайтах можно запросто перезапустить полный обмен.
Многие задачи могут быть решены на стороне сайта без переписывания типового обмена. Но без качественного инструмента заниматься решением проблем с интеграцией очень тяжело.
Следует всегда закладывать в бюджет проекта стоимость интеграции, поддержку интеграции и инструменты.
Коллеги, пожалуйста, если вы примените модуль, напишите какие цифры по ускорению обмена вы получили при включении модуля на своем проекте. И сколько всего свойств в инфоблоке у вас.
Чтобы точно проверить быструю запись свойств, нужно отключить в настройках магазина в интеграции с 1С опцию Использовать контрольные суммы. Если опция будет включена, то при втором запуске будет очень быстро. Потому что товар вообще не будет перезаписан.
Еще наш модуль пишет время записи в лог при записи элемента. Можно быстро тестировать с одним товаром и смотреть лог-файл.
Когда-то мы сделали модуль «Управление почтой» для решения многих задач. Письма с сайта можно просматривать и отправлять повторно.
Проблема неотправленных писем особенно актуальна для неспециализированных хостингов типа Ру-Центра (тариф 201, 301), где письма уходят не всегда из-за ограничений на оперативную память.
В версии 1.2.0 добавлена автоматическая проверка и повторная отправка для неушедших писем:
Опции включаются в настройках модуля: Настройки -> Настройки продукта -> Настройки модулей -> Управление почтой.
Реализация:
Модуль работает на агентах на хите пользователя. Крон настраивать не обязательно.
Антон Долганин, где-то писал, что скрипт, вызванный кроном, отдельно подключает расширения PHP, и поэтому потребляет лишнюю память. Для нашей задачи расход памяти критичен, поэтому агент на хитах - лучший вариант.
По умолчанию агент запускается через 2 минуты после своего последнего запуска.
Нет особого смысла ставить короткий период в 2 секунды. В PHP память освобождается не мгновенно, нужно какое-то время. Если письмо не ушло из-за нехватки памяти в момент отправки, лучше подождать 2 минуты.
Опция «Записывать в лог» делает лишний запрос на чтение к базе данных, но напишет подробный отчет в лог, если найдены неотправленные письма.
UPD 23.10.2013
Ру-Центр сделал новый специализированный тариф под Битрикс на 704 Мб оперативной памяти.
Соответственно Битрикc считает, что почтовое событие сработало со статусом Y и исправлять его не надо
echo CEvent::Send( "TEST", "s1", array("EMAIL" => "<ma!il@ask>a<ron.ru>" ), "N" );
Если адрес пустой, функция mail вернет false:
var_dump( mail( "", "test", "test" ) ); // false
А почтовое событие завершится со статусом F
echo CEvent::Send( "TEST", "s1", array("EMAIL" => "" ), "N" );
Потом наш модуль будет повторно отправлять это письмо и писать в лог каждый раз, если лог включен.
=========
Я с трудом себе представляю случай, когда адрес получателя пустой. В любом случае администратор может просматривать все письма со статусами на отдельной странице, пользоваться фильтром и удалять ненужные события руками.
По ссылке мой функционал, который автоматизирует переотправку писем. Заметьте не исправляет ошибки, а перезапускает почтовые события на отправку. То есть условие, что почта работала и до этого отлично, но письма периодически встают.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».
localedef -c -i ru_RU -f CP1251 ru_RU.CP1251