#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. Попробуйте сами.