PHP: выходить и показывать предупреждение, когда зацикливание очень длинной функции не отвечает - PullRequest
0 голосов
/ 14 июля 2010

У меня есть эта большая функция (более 1300 строк кода), которая берет данные из Интернета и вставляет их в локальную базу данных. Каждый раз, когда функция запускается, требуется около 20 секунд, и мне нужно запускать эту функцию миллион раз, поэтому я использую set_time_limit (0), чтобы установить ограничение времени PHP на бесконечность, и я зацикливаю функцию миллион раз, как это:

for ($ID= '01'; $ID < '999999'; $ID++) {
    getDataFromWeb($conn, $ID);
}

Так в чем проблема? Проблема в том, что есть миллион вещей, которые могут пойти не так, и всегда идут не так, и вдруг код застревает в ID 23465, например, и он просто прекращает получать данные, но я не получаю никакой ошибки, это как цикл продолжается, но без вставки чего-либо в базу данных, и из-за «без ограничения времени» я установил PHP, тогда он никогда не останавливается.

Я хочу знать, как я могу обнаружить такую ​​проблему, остановить все и показать предупреждение. Если я установил время до запуска функции, а затем проверил его, когда функция заканчивается, как показано ниже:

for ($ID= '01'; $ID < '999999'; $ID++) {
    $time_start = microtime();
    getDataFromWeb($conn, $ID);
    $time_end = microtime();
    if ($time_alert - //... somehow check how time does it takes and stop if its taking too much
}

Это не будет работать, потому что если функция никогда не завершится, $ time_end никогда не будет установлен и так далее ...

Итак, помогите, пожалуйста?

Ответы [ 5 ]

1 голос
/ 14 июля 2010
0 голосов
/ 14 июля 2010

Примечание: предоставленный код не будет зацикливаться 1 000 000 раз.Следующее будет:

for( $id=1 ; $id<=1000000 ; $id++ ) {
    getDataFromWeb( $conn , $id );
}

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

  • Я полагаючто вы используете таблицу SQL для хранения просматриваемых URL-адресов,
  • Добавьте поле с отметкой времени с именем «loadAttempted»,
  • Ограничьте сценарий PHP, чтобы попытаться выполнить действие, возможно,5 раз,
  • Записать время, когда скрипт пытается сканировать URL в поле «loadAttempted»,
  • Каждый цикл скрипта должен выполнять поиск любых URL, где «loadAttempted» пустили где оно больше X минут назад,
  • Добавить задание CRON для запуска сценария

Это будет означать, что до каждой минуты сценарий будет запускаться ипостараюсь загрузить 5 URL.Если для загрузки URL-адреса требуется слишком большой промежуток времени (что может означать, что время выполнения скрипта истекло во время попытки его сканирования), оно будет возвращаться назад и повторяться.

Вы также можете использовать это, иливарианты идеи, чтобы получить статистику для страниц, которые медленнее остальных и / или среднее время загрузки для URL.

Кроме того, если вы хотите, чтобы это работало постоянно, я бы предложил ограничитьPHP-скрипт для запуска функции getDataFromWeb() меньшее количество раз (например, 5)

0 голосов
/ 14 июля 2010

Есть ли у вас функции mysql_error () / mysql_errno () в вашей функции getDataFromWeb ()?Например,

if(mysql_errno($conn))
{ 
  echo mysql_errno($conn) . ": " . mysql_error($conn);
}

С http://php.net/manual/en/function.mysql-error.php

Для остановки функции замените эхо-сигнал на матрицу.

0 голосов
/ 14 июля 2010

Ладно, здесь есть несколько вещей, которые мне по душе.

Во-первых, вы не шутили, когда сказали, что повторяете этот миллион раз. Это меня удивило.

Второе - этот цикл мне кажется странным:

for ($ID= '01'; $ID < '999999'; $ID++)

Почему бы вместо этого не сделать:

for ($ID = 1; $ID < 999999; $ID++)

Я не понимаю, почему вы используете строки для подсчета целых чисел.

Третье. Как вы это выполняете? Это из браузера или из CLI

Наконец, - не видя кода, трудно сказать, что происходит, но возвращает ли функция логическое значение true / false после завершения или их другие триггеры, такие как операторы echo (как минимум), в функции, которая будет печатать отладку информация, чтобы вы могли отслеживать прогресс.

Возможно, вы захотите упростить код в функции getDataFromWeb, похоже, он выполняет какой-то запрос cURL, анализирует эти данные и помещает его в базу данных "$ conn". Может быть проще не только понять, но и прочитать, если вы разбили конкретные задачи из этой функции на отдельные функции (или создали класс) Одна для получения данных, одна для «очистки» данных и одна для ввода данных в базу данных. Если у функции слишком много задач, такие проблемы (отладка) становятся кошмаром.

0 голосов
/ 14 июля 2010

Если getDataFromWeb($conn, $ID); использует библиотеки типа libcurl или аналогичные, чем, может быть, стоит установить ограничение времени подключения? Или для отладки просто echo '.', чтобы узнать, что функция завершена и завершена.

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