Медленные cronjobs на Cent OS 5
У меня есть 1 cronjob, который запускается каждые 60 минут, но по какой-то причине в последнее время он работает медленно.
Env: centos5 + apache2 + mysql5.5 + php 5.3.3/raid 10/10k HDD/16gig ram/4 xeon процессор
Вот что делает cronjob:
-
проанализировать последние 60-минутные данные
a) 1 обрабатывает пользовательский агент и сохраняет данные в базе данных
b) 1 процесс анализирует показы/клики на веб-сайте и сохраняет их в базе данных
-
из данных на шаге 1
a) создайте небольшой отчет и отправьте электронные письма администратору /bussiness
b) сохранить отчет в ежедневную таблицу (доступную в разделе администратора)
Я вижу теперь 8 процессов (тот же файл), когда я запускаю команду ps auxf | grep process_stats_hourly.php
(нашел эту команду в stackoverflow)
Технически я должен иметь только 1 не 8.
Есть ли какой-либо инструмент в Cent OS или что-то, что я могу сделать, чтобы убедиться, что мой cronjob будет работать каждый час и не накладываться на следующий?
Спасибо
Ответы
Ответ 1
Ваше оборудование кажется достаточно хорошим, чтобы обработать это.
1) Проверьте, есть ли у вас уже существующие процессы. Используя ps auxf
(см. Ответ tcurvelo), проверьте, есть ли у вас один или несколько процессов, требующих слишком много ресурсов. Возможно, у вас недостаточно ресурсов для запуска вашей cronjob.
2) Проверьте сетевые подключения:
Если ваши базы данных и ваш cronjob находятся на другом сервере, вы должны проверить, какое время ответа между этими двумя машинами. Возможно, у вас есть проблемы с сетью, которые заставляют cronjob ждать, пока сеть вернет пакет.
Вы можете использовать: Netcat, Iperf, mtr или ttcp
3) Конфигурация сервера
Правильно ли настроен ваш сервер? Ваша ОС, MySQL настроены правильно? Я бы рекомендовал прочитать следующие статьи:
http://www3.wiredgorilla.com/content/view/220/53/
http://www.vr.org/knowledgebase/1002/Optimize-and-disable-default-CentOS-services.html
http://dev.mysql.com/doc/refman/5.1/en/starting-server.html
http://www.linux-mag.com/id/7473/
4) Проверьте вашу базу данных:
Убедитесь, что ваша база данных имеет правильные индексы и убедитесь, что ваши запросы оптимизированы. Прочтите эту статью о объясните команду
Если запрос с несколькими сотнями тысяч записей требует времени для выполнения, это повлияет на остальную часть вашего cronjob, если у вас есть запрос внутри цикла, еще хуже.
Прочтите следующие статьи:
http://dev.mysql.com/doc/refman/5.0/en/optimization.html
http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
http://blog.fedecarg.com/2008/06/12/10-great-articles-for-optimizing-mysql-queries/
5) Трассировать и оптимизировать PHP-код?
Убедитесь, что ваш PHP-код работает как можно быстрее.
Прочтите следующие статьи:
http://phplens.com/lens/php-book/optimizing-debugging-php.php
http://code.google.com/speed/articles/optimizing-php.html
http://ilia.ws/archives/12-PHP-Optimization-Tricks.html
Хорошая техника для проверки вашей кроны - проследить ваш cronjob script:
На основе вашего процесса cronjob поместите некоторую трассировку отладки, включая объем памяти, сколько времени потребовалось для выполнения последнего процесса. например:
<?php
echo "\n-------------- DEBUG --------------\n";
echo "memory (start): " . memory_get_usage(TRUE) . "\n";
$startTime = microtime(TRUE);
// some process
$end = microtime(TRUE);
echo "\n-------------- DEBUG --------------\n";
echo "memory after some process: " . memory_get_usage(TRUE) . "\n";
echo "executed time: " . ($end-$start) . "\n";
Посредством этого вы можете легко найти, какой процесс занимает столько памяти и сколько времени потребуется для его выполнения.
6) Внешние серверы/вызовы веб-службы
Ваш cronjob вызывает внешние серверы или веб-сервис? если это так, убедитесь, что они загружены как можно быстрее. Если вы запрашиваете данные со стороннего сервера, и этот сервер занимает несколько секунд, чтобы вернуть ответ, который будет влиять на скорость вашего cronjob специально, если эти вызовы находятся в циклах.
Попробуйте и дайте мне знать, что вы найдете.
Ответ 2
Вывод ps
также показывает, когда процесс начался (см. столбец STARTED
).
$ ps auxf
USER PID %CPU %MEM VSZ RSS TTY STAT STARTED TIME COMMAND
root 2 0.0 0.0 0 0 ? S 18:55 0:00 [ktrheadd]
^^^^^^^
(...)
Или вы можете настроить вывод:
$ ps axfo start,command
STARTED COMMAND
18:55 [ktrheadd]
(...)
Таким образом, вы можете быть уверены, что они перекрываются.
Ответ 3
Вы должны использовать механизм блокировки в вашем process_stats_hourly.php script. Не обязательно быть слишком сложным, вы могли бы написать PHP файл PID, который запустил процесс в файл, например /var/mydir/process _stats_hourly.txt. Поэтому, если для обработки статистики требуется больше часа, а cron запускает другой экземпляр process_stats_hourly.PHP скрипт, он может проверить, существует ли файл блокировки, если он не будет работать.
Однако у вас остается проблема с тем, как "перезаписывать" часовой параметр script, если он нашел файл блокировки и не смог запустить.
Ответ 4
Вы можете использовать strace -p 1234
, где 1234 - соответствующий идентификатор процесса, в одном из процессов, который работает слишком долго. Возможно, вы поймете, почему это так медленно или даже заблокировано.
Ответ 5
Есть ли какой-либо инструмент в Cent OS или что-то, что я могу сделать, чтобы убедиться, что мой cronjob будет работать каждый час и не накладываться на следующий?
Да. Стандартный пакет util-linux
CentOS обеспечивает удобство командной строки для блокировки файловой системы. Как показано в Digital Precision , файл блокировки - это простой способ синхронизации процессов.
Попробуйте вызвать свой cronjob следующим образом:
flock -n /var/tmp/stats.lock process_stats_hourly.php || logger -p cron.err 'Unable to lock stats.lock'
Вам нужно будет отредактировать пути и при необходимости настроить PATH. Этот вызов попытается заблокировать stats.lock
, создав статистику script в случае успеха, иначе отказавшись и зарегистрировав отказ.
В качестве альтернативы ваш script может вызвать PHP flock() для достижения такого же эффекта, но утилита flock(1)
уже существует для вас.
Ответ 6
Как часто этот файл журнала вращается?
Лог-синтаксическое задание неожиданно занимает больше времени, чем обычно, так как журнал не поворачивается и теперь слишком велик для эффективного анализа парсером.
Попробуйте сбросить файл журнала и посмотреть, работает ли работа быстрее. Если это решает проблему, я рекомендую logrotate как средство предотвращения проблемы в будущем.
Ответ 7
Вы можете добавить шаг к cronjob, чтобы проверить вывод своей команды:
ps auxf | grep process_stats_hourly.php
Продолжайте цикл до тех пор, пока команда ничего не вернет, показывая, что процесс не запущен, а затем разрешите выполнение оставшегося кода.