Рекомендации / Хитрости по регулированию PHP-скрипта

StackOverflow https://stackoverflow.com/questions/752337

  •  09-09-2019
  •  | 
  •  

Вопрос

У меня есть запланированная задача, которая запускает скрипт на регулярной основе (каждый час).Этот скрипт выполняет некоторое интенсивное взаимодействие с базой данных и файловой системой, и его запуск обычно занимает несколько минут.Проблема в том, что загрузка процессора сервера резко возрастает во время выполнения скрипта и замедляет нормальную работу.Есть ли способ ограничить этот процесс, чтобы он занимал больше времени, но не потреблял так много ресурсов?

Я просмотрел различные варианты конфигурации для PHP, но, похоже, нет ни одного, который соответствовал бы моим потребностям.

Установка memory_limit в php.ini на что-то меньшее приводит к тому, что мои объекты данных довольно легко переполняются.

Я видел похожие сообщения, где люди предлагали использовать sleep() в определенных точках скрипта, но это не мешает скрипту запускать сервер.

Оптимальным решением было бы каким-то образом указать стеку Lamp (в данном случае Wamp) использовать только 10% максимальной загрузки процессора.Я вообще не беспокоюсь о времени выполнения и предпочел бы, чтобы это заняло больше времени, если это означает экономию циклов процессора в секунду.Моим альтернативным решением было бы настроить другой сервер с репликацией базы данных, чтобы cron мог работать в городе, не замедляя работу всего остального.

Окружающая среда:Windows Server 2k3, Apache 2.2.11, PHP 5.2.9, MySQL 5.1

Я ценю любое понимание этой ситуации.

Редактировать: Я ценю все ответы, даже те, которые зависят от *nix.В моей ситуации еще достаточно рано менять среду хостинга.Надеюсь, этот вопрос поможет другим, независимо от операционной системы.

Это было полезно?

Решение

Это сложная проблема.Если вы запускаете PHP-скрипт через командную строку, вы можете установить низкий приоритет планирования процесса (start /low php.exe myscript.php Я считаю).Если ваш PHP-скрипт сам выполняет большую часть обработки, потребляющей ваш процессор, это может сработать.Однако вы сказали, что выполняете тяжелое взаимодействие с базой данных и файловой системой, и это решение не поможет.Похоже, что есть подсказка MySQL «LOW_PRIORITY» для запросов INSERT и UPDATE, которая может вам в этом помочь, но я ее не пробовал.

Другие советы

Вы можете установить процессы в Windows с более низким приоритетом. Я не уверен, как этот процесс запускается, но если вы установите для процесса низкий приоритет, все, кому нужны ресурсы ЦП, получат их, если вы установите очень низкий приоритет.

В UNIX (ЛАМПА) Мне удалось решить проблему, проверив загрузку сервера перед продолжением цикла.

function get_server_load($windows = 0) {
    $os = strtolower(PHP_OS);
    if(strpos($os, "win") === false) {
        if(file_exists("/proc/loadavg")) {
         $load = file_get_contents("/proc/loadavg");
         $load = explode(' ', $load);
         return $load;
        }
        elseif(function_exists("shell_exec")) {
         $load = explode(' ', `uptime`);
         return $load;
        }
        else {
         return "";
        }
    }
}

for(... ... ...){
    $data = get_server_load(); 
    if($data[0] < 0.2){
     // continue
    }else{
        sleep(1);
    }
}

Эта функция должна работать и в Windows, но я не могу этого гарантировать.В Linux он возвращает массив с загрузкой за последнюю минуту, 5 минут и 15 минут.

Кроме того, рассмотрите возможность запуска ваших сценариев (если через CLI) с более низким приоритетом (в Linux используйте «nice»)

Вы также можете использовать другие значения, прежде чем продолжить цикл, например, количество активных процессов Apache (вы можете проанализировать страницу 127.0.0.1/server_status?auto, если вы включили mod_status в httpd.conf), или также ситуацию MySQL (активные соединения ?)

Можете ли вы изменить запись cron, чтобы запустить скрипт, используя хороший?

Не хорошая идея использовать сервер для обслуживания клиентов и анализа данных.

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

Даже если вам удастся успешно ограничить работу анализатора, он будет использовать драгоценные ресурсы, в противном случае он будет доступен для обслуживания пользователей.

Это может оказаться трудным изменением, но, возможно, стоит провести рефакторинг структур данных в итераторы.Кроме того, если в вашем коде есть циклические ссылки, предоставьте такой метод, какclearReferences(), который сбрасывает настройки этих объектов.Кстати, эта проблема решена в PHP 5.3.

Итак, если у вас есть:

class Row
{
    protected $_table;

    public function __construct($table)
    {
        $this->_table = $table;
    }
}

class Table
{
    protected $_row;

    public function __construct()
    {
        $this->_row = new Row($this);
    }
}

Добавьте метод ClearReferences() в класс Row:

class Row
{
    public function clearReferences()
    {
        $this->_table = null;
    }
}

Это все, что я могу придумать на данный момент.

У меня есть несколько скриптов, которые я запускаю из cron аналогичным способом, используя nice:

0 * * * * приятно -n19 php myscript.php

Это не улучшит использование оперативной памяти (это можно сделать, только изменив способ написания сценария), но будет использоваться только тот процессор, который в противном случае простаивал бы.

РЕДАКТИРОВАТЬ:не увидел, что вопрос касается среды Windows, извините...оставив это для всех пользователей *nix, имеющих ту же проблему..

Возможно, ваш сценарий просто пытается сделать слишком много одновременно.Будет ли он работать меньше, если будет работать три раза в час?

Другим решением может быть установка дополнительного сервера только для выполнения такого рода «внутренней» обработки.Это будет особенно эффективно, если это не создает чрезмерную нагрузку на базу данных, а только на веб-сервер.

Еще один подход, на который следует обратить внимание, заключается в том, можно ли разделить работу в другом направлении.Сценарии такого типа часто содержат несколько больших операторов SQL, которые генерируют результаты, используемые для генерации множества маленьких операторов SQL.Если последние можно куда-то отложить, их можно будет запустить в базе данных на более позднем этапе.Такой подход также может позволить вам использовать небуферизованный запрос для получения данных предварительной обработки, что может значительно сократить потребление памяти кодом PHP.

Если у вас он (Apache) запущен как служба, вы можете изменить приоритет настройки в Центре управления Win / services.Загрузка вашего процессора все равно возрастет, но планировщик предпочтет другие программы .Также попробуйте установить базу данных / сервер на другом жестком диске, отличном от вашего Приложения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top