Подтвердить что ты не робот

Медленные 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 будет работать каждый час и не накладываться на следующий?

Спасибо

4b9b3361

Ответ 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

Продолжайте цикл до тех пор, пока команда ничего не вернет, показывая, что процесс не запущен, а затем разрешите выполнение оставшегося кода.