Как я могу изящно сделать тайм-ауты PHP-скриптов в ожидании длинных запросов MySQL? - PullRequest
9 голосов
/ 14 мая 2010

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

Ожидая обычных ответов на этот вопрос:

  1. «Оптимизируйте свои запросы, чтобы они не выполнялись так долго» - я регистрирую долгосрочные запросы и оптимизирую их, но я знаю об этом только после того, как на пользователя повлияло. *

  2. «Увеличьте настройку тайм-аута PHP (например, set_time_limit, max_execution_time), чтобы длительный запрос мог завершиться» - иногда запрос может выполняться в течение нескольких минут. Я хочу сообщить пользователю, что до этого возникла проблема (например, через 30 секунд).

  3. «Использовать register_tick_function для отслеживания того, как долго выполняются сценарии» - это выполняется только между строками кода в моем сценарии. Пока скрипт ожидает ответа от базы данных, функция галочки не вызывается.

Если это помогает, сайт построен с использованием Drupal (с большим количеством настроек) и работает на виртуальном выделенном сервере Linux на PHP 5.2 с MySQL 5.

Ответы [ 3 ]

3 голосов
/ 14 мая 2010

Нет асинхронных вызовов mysql и нет возможности для разветвления легких потоков.

Хотя вы можете разделить свой PHP-код на два уровня и использовать соединение между ними, которое вы можете вызывать асинхронно, проблема с этим подходом заключается в том, что уровень БД все еще будет пытаться выполнить запрос после того, как верхний уровень прекратил получать результаты обратно - потенциально блокирование СУБД для других пользователей. (вы чаще будете получать запросы на страницы, время которых истекло).

У вас возникнет та же проблема, если вы увеличите время ожидания в обратном прокси-сервере, расположенном перед веб-сервером.

Самым разумным местом для реализации тайм-аута является сама база данных - но AFAIK, mysql не поддерживает это.

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

Однако, принимая другой подход к модели прокси - вы можете порождать отдельный процесс PHP с помощью proc_open и установить поток stdout как неблокирующий - таким образом ваш PHP может продолжать работать и проверять, запущен ли прокси запрос. Если время ожидания истекло, то в качестве родителя прокси-сервера он может сигнализировать об отключении (proc_terminate ()), что должно остановить выполнение запроса в базе данных.

Конечно, это будет означать большую работу по разработке.

Может оказаться намного проще настроить одну или несколько подчиненных СУБД для выполнения ваших медленных запросов - возможно, с интеллектуальной балансировкой нагрузки. Или посмотрите другие способы ускорения медленных запросов - например, предварительную консолидацию.

НТН

С

0 голосов
/ 14 мая 2010

Ваш сервер настроен с APC, Memcache, Boost и Drupal Cache? Это альтернативные маршруты, которые работают очень хорошо.

Иначе, какие скрипты работают в Drupal, что могло бы вызвать это? Просто из любопытства, у вас запущены виды и панели?

0 голосов
/ 14 мая 2010

обработка соединений документы - это то, что вам нужно.

Как правило, вам необходимо зарегистрировать функцию выключения, используя register_shutdown_function () . Эта функция будет вызываться всякий раз, когда сценарий завершается, независимо от того, успешно ли он завершен, отменен пользователем (клавиша ESC) или истек тайм-аут.

Эта функция отключения может затем вызывать функцию connection_status () . Если connection_status () возвращает 2 (TIMEOUT), а предыдущая страница была той, на которой выполнялся проблемный запрос, вы можете перенаправить пользователя на страницу с текстом «Извините, но сейчас у нас высокая загрузка сервера». 1012 * или что угодно.

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