Запуск нескольких PHP CLI в фоновом режиме дает ошибки MySQL

Мы используем мета-поисковую систему (сравнение цен), где каждый поиск порождает несколько поисковых запросов в реальном времени на различных веб-сайтах и ​​представляет объединенные и отсортированные результаты поиска на нашем сайте.

Мы используем PHP/MySQL/Apache на Linux-сервере Debian в довольно простой конфигурации, но фоновая обработка параллельного поиска по нескольким сайтам выполняется Tomcat и Java-сервлетом. Однако из-за некоторых проблем с этой настройкой (Tomcat) я изучаю новые подходы к фоновому поиску.

Один способ, который выглядит многообещающе, также очень прост: на главной странице поиска каждый отдельный скрипт поиска запускается как PHP CLI с использованием exec():

exec("nohup /usr/bin/php search.php '$params' &> /dev/null &");

Использование амперсанда в конце отправляет сценарии PHP CLI непосредственно в фоновый режим, и главная страница может продолжаться без ожидания. Для каждого поиска выполняется около 20 скриптов.

Кажется, он работает достаточно хорошо, но когда я запускаю стресс-тест с использованием Apache Benchmark с параллельными запросами, проблемы начинают обнаруживаться. Что происходит, что MySQL сообщает об этой ошибке:

Не удается подключиться к локальному серверу MySQL через сокет '/var/run/mysqld/mysqld.sock' (11)

Кажется, это вариант "Слишком много подключений", но это не помогает поднять ограничения в my.cnf. Но что меня действительно озадачивает, так это то, что эти ошибки присутствуют, даже если я вызываю небольшой фиктивный скрипт, который ничего не делает и, конечно, не имеет доступа к MySQL. Таким образом, похоже, что запуск PHP CLI создает нагрузку на MySQL, даже если он не используется.

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

Кто-то имеет представление о проблеме MySQL? И, конечно же, я открыт для новых идей о том, как справляться с фоновыми задачами!

С уважением, Мартин

3 ответа

Мартин,

Я определенно не эксперт в этом, но на ум приходит пара вещей.

Я думаю, что php загружает поддержку mysql независимо от того, используете ли вы его или нет в своем скрипте, но он не должен запускать соединение, если вы не используете постоянные соединения. Я не думаю, что сценарии cli наследуют соединение mysql от Apache ребенок, но, видимо, это должно основываться на вашем тестировании.

Вы также можете столкнуться с ограничением слишком большого количества файлов в MySQL. Существует также ссылка на нехватку ОЗУ / ресурсов, являющихся причиной ошибки mysql. Вы сказали, что он показывает меньшую нагрузку, чем ваши старые настройки, но может ли это быть слишком много? Когда эти сценарии выполняются, есть ли возможность установить соединение с сервером MySQL через графический интерфейс (администратор MySQL)? Если это так, вы можете увидеть, что у него закончились ресурсы...

С точки зрения базы данных может оказаться более эффективным, чтобы ваши 20 запросов выполнялись только в одном сценарии, а не в нескольких сценариях. Это позволит вам использовать одно соединение mysql для всех 20 поисков и соответственно увеличит пропускную способность вашего соединения. Другими словами, Web Script ---- порождает -----> CLI-скрипт в фоновом режиме, который просматривает все ваши поиски.
Не зная ваш код или точно, что вы делаете, это всего лишь предположение, как исправление кода.

Удачи

Я бы сказал, что нерест рабочих мест слишком прост и, безусловно, может привести к нехватке ресурсов.

Чтобы избежать этого, я бы использовал некоторую форму очереди - либо через таблицу базы данных, которая перечисляет то, что требуется, а затем регулярно проверяется, либо через систему очередей заданий, что-то вроде Gearman или Beanstalkd. Вы помещаете сообщение в очередь - то, что вы хотите найти - и фоновое задание, которое уже выполняется, которое подбирает задания по мере их поступления и имеет возможность, выполняет соответствующие задания и передает информацию обратно, либо через БД, либо через систему в памяти, такую ​​как Memcached. Внешняя система может обновить (или использовать Ajax), чтобы перезвонить и посмотреть, была ли найдена какая-либо информация, отображая ее соответствующим образом.

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

Извините за задержку с ответом. Я был болен гриппом.

Спасибо за ваш отзыв. Есть о чем подумать!

Я провел еще несколько экспериментов с вызовом сценариев с помощью wget, а не сценариев CLI, и, кроме того, Lighttpd обслуживает эти специальные сценарии поиска на порте 81 - чтобы снять нагрузку с основного сервера Apache.

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

Изменить: Я оригинальный постер, не знаю, почему он выглядит как чей-то пост. Возможно, что-то с моим OpenID...

Другие вопросы по тегам