Параллельная обработка / разветвление в PHP для ускорения проверки больших массивов

#php #optimization #fork

#php #оптимизация #разветвление

Вопрос:

На моем веб-сайте есть php-скрипт, который предназначен для предоставления хорошего обзора доменного имени, которое вводит пользователь. Он выполняет эту работу довольно хорошо, однако это очень медленно. Это может быть как-то связано с тем фактом, что проверяется массив из 64 возможных доменных имен, а ЗАТЕМ переходит к проверке серверов имен на наличие записей A / MX / NS и т.д.

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

Я поместил пример своего кода в pastebin (чтобы избежать создания огромного и спам-сообщения здесь)http://pastebin.com/Qq9qKtP9

В perl я могу сделать что-то вроде этого:

   $fork = new Parallel::ForkManager($threads);
  foreach(Something here){
  $fork->start and next;
  $fork->finish;
  }
  

И я мог бы запустить цикл в стольких процессах, сколько необходимо. Возможно ли что-то подобное в PHP или любые другие способы, которые вы можете придумать, чтобы ускорить это? Основная проблема заключается в том, что у cloudflare есть тайм-аут, и часто это занимает достаточно много времени, CF блокирует получение ответа.

Спасибо

Комментарии:

1. Возможно, это неправильное решение, но есть Gearman .

2. Можете ли вы установить расширения php? (pthreads) Если нет, разрешено ли вам вызывать функции pcntl_ *?

3. Я могу установить любое расширение, которое мне нужно. Это на Ubuntu VPS, и у меня есть root-доступ. И является ли pthreads лучшим решением для этого тогда?

Ответ №1:

* Не обращайте внимания на поддержку!! *

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

Если вашему интерфейсу дано указание создавать 60 потоков каждый раз, когда кто-то нажимает на page.php , и 100 человек приходят и запрашивают page.php одновременно, вы будете просить свое оборудование создать и выполнить 6000 потоков одновременно, не говоря уже о потоках, используемых службами операционной системы и другим программным обеспечением. По очевидным причинам это не масштабируется и никогда не будет масштабироваться.

Скорее вы хотите отделить те части приложения, которые требуют дополнительных потоков или процессов, и взаимодействовать с этой частью приложения через какой-нибудь нормальный RPC. Это означает, что серверная часть приложения может использовать параллелизм через pthreads или разветвление, используя фиксированное количество потоков или процессов и распределяя работу как можно более равномерно по всем доступным ресурсам. Это обеспечивает приток трафика; это позволяет вашему приложению масштабироваться.

Я не буду писать пример кода, это кажется слишком тривиальным.

Ответ №2:

Первое, что вы хотите сделать, это оптимизировать свой код, чтобы максимально сократить время выполнения. Например, вместо выполнения пяти dns-запросов:
$NS = dns_get_record($murl, DNS_NS);
$MX = dns_get_record($murl,DNS_MX);
$SRV = dns_get_record($murl,DNS_SRV);
$A = dns_get_record($murl,DNS_A);
$TXT = dns_get_record($murl,DNS_TXT);

Вы можете вызвать dns_get_record только один раз:
$DATA = dns_get_record($murl, DNS_NS DNS_MX DNS_SRV DNS_A DNS_TXT);
и проанализировать переменные оттуда.

Вместо прямого разветвления процессов для одновременной обработки нескольких частей я бы внедрил очередь, в которую будут помещаться все запросы. Процессор запросов был бы ограничен в том, сколько элементов он мог бы обрабатывать одновременно, избегая потенциального DOS, если сотни или тысячи запросов попадают на ваш сайт одновременно. Без какого-либо механизма ограничения у вас в конечном итоге будет так много процессов, что сервер может зависнуть.
Что касается процессора, в дополнение к ранее упомянутым элементам, вы могли бы попробовать pecl / Gearman в качестве вашего процессора очередей. Я не использовал это, но, похоже, оно делает то, что вы ищете.

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

Комментарии:

1. Вы можете не внедрять кэш самостоятельно, если используете локальный DNS-сервер с включенным кэшем.

2. Не было бы более эффективным использовать кэш SQL, предполагая, что SQL server уже используется и имеет постоянное соединение? Как минимум, вы сэкономили бы накладные расходы на создание нового сетевого подключения.

Ответ №3:

Я сомневаюсь, что это хорошая идея — разветвлять процесс apache с помощью PHP. Но если вы действительно хотите, есть PCNTL (который недоступен в модуле apache).

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

И, наконец, у вас есть возможность использовать классический неблокирующий ввод-вывод, который я бы предпочел в случае PHP.

Комментарии:

1. Почему вы не думаете, что это было бы неплохо сделать? Этот VPS предназначен для веб-сайта, поэтому использование всех доступных ресурсов при сверхвысокой нагрузке не является проблемой.

2. ИМО просто кажется неправильным, что модуль apache разветвляет процесс apache. Честно говоря, я не знаю, что произойдет. Тот факт, что я написал «Я сомневаюсь», а не «Это не так», отражает то, что это всего лишь мнение. Кроме того, кажется невозможным использовать PCNTL в качестве модуля apache. Попробуйте сами.