PHP 7 обрабатывает запросы асинхронно по умолчанию? - PullRequest
0 голосов
/ 28 февраля 2019

Я пишу PHP последние 3,5 года, и мне это нравится.Когда появилось недавнее жужжание PHP v / s Nodejs , одна вещь, которая всегда была в центре внимания, это то, что Nodejs реализовал неблокирующий (или асинхронный) ввод / вывод по умолчаниюа PHP нет.

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

Прежде чем продолжить объяснение, я хотел бы, чтобы вы ознакомились с кодом ниже.

sync.php : тот, который должен отложить все дальнейшие запросы до тех пор, пока текущий не завершит обработку :

<?php
    $a = $argv[1];
    echo "starting: ".$a;
    $ar = array();
    $sum = 0;
    $ul = 15000;
    for($i = 1; $i < $ul; $i++){
        $ar[$i] = $i;
    }
    for($i = 1; $i < $ul;  $i++){
        for($j = 1; $j < $ul; $j++){
            $sum += $ar[$j];
        }
    }
    echo "\n\nDone: ".$a."\nResult: ".$sum."\n";
?>

Я сделал два вида тестов.

Сначала я запустил четыре экземпляра терминала на моем компьютере и выполнил:

php sync.php 1  

во всех них одновременно .

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

РЕЗУЛЬТАТЫ НЕ ОЖИДАЛИСЬ.

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

Это не соответствует тому факту, что PHP реализует блокировку ввода / вывода (это то, что происходит со мной).Вместо этого я ожидал получить общее время пакета

n * 4 seconds

, где n - время, необходимое для обработки каждого запроса (примерно 8 секунд на моем ноутбуке).

Итак, почему запросы обрабатываются асинхронно ??Это потому, что for loop является одной из функций, которые выполняются асинхронно, или она вообще не имеет отношения к блокирующей модели ввода / вывода ??

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Вы неправильно поняли, что обсуждается в отношении блокировки ввода-вывода.

Каждый раз, когда вы запускаете скрипт PHP из командной строки, он выполняется в совершенно отдельном процессе, который не знает ни о какомдругой скрипт PHP, работающий на машине.Вы можете выполнить его несколько раз по одной и той же причине, по которой вы можете запускать веб-браузер и текстовый редактор одновременно - ОС планирует процессы на одном или нескольких процессорных ядрах.

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

Какие людиобсуждается, что блокировка ввода-вывода - это нечто совершенно иное: когда вы получаете доступ к чему-то внешнему внутри вашего PHP-кода, например, извлекаете веб-контент с помощью HTTP-запроса.Представьте себе этот цикл, используя воображаемую библиотеку HTTP:

foreach ( $urls as $url ) {
    $results[] =  $httpClient->fetchUrl($url);
}

Если записано с использованием встроенной функции PHP, перестанет работать и будет ждать, пока удаленный сервер ответит каждый разпетля.Таким образом, для 10 запросов, каждый из которых занимает секунду, для завершения цикла потребуется 10 секунд.

«Неблокирующий ввод / вывод» означает реализацию таких функций, как fetchUrl, чтобы они немедленно возвращали хотя ответ HTTP не вернулся.Таким образом, вы можете запустить много HTTP-запросов одновременно: в цикле примера вы получите все 10 ответов через 1 секунду.Тогда у вас будет какой-то способ получить результаты, например, «обещание».

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

Еще сложнее, система может реализовать это для input : всякий раз, когда вы ожидаете чего-то внешнего, вы можете проверить, поступил ли новый веб-запрос, и начать его обработку.Это может эффективно имитировать несколько потоков, что позволяет NodeJS обрабатывать большой объем трафика с потоком на запрос.

0 голосов
/ 28 февраля 2019

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

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

Поскольку по очевидным причинам это проблематично, если на ваш сайт одновременно заходят тысячи людей, существует простое решение - несколько процессов PHP .Это может быть настроено различными способами - Apache запустит несколько рабочих веб-серверов , или вы можете запустить PHP-FPM ("FastCGI Process Manager" ).

Пока их свободные рабочие сидят, они будут обрабатывать входящие запросы параллельно.

...