Как делать асинхронные HTTP-запросы в PHP?
Асинхронный HTTP-запрос помогают нам обрабатывать HTTP-запросы с использованием неблокирующего ввода или вывода в разных потоках. Некоторые называют это возможностями COMET . Основное использование асинхронных HTTP-запросов — это когда клиент запрашивает у сервера поздний ответ. Типичным примером является клиент чата AJAX , в котором мы отправляем или извлекаем данные как с клиента, так и с сервера. Эти сценарии блокируют клиента на длительное время в сокете сервера в ожидании нового сообщения.
PHP обслуживает запросы синхронно. Это означает, что каждая строка кода выполняется синхронно сценария. После получения результата из одной строки он выполняет следующую строку или ожидает результата, прежде чем перейти к выполнению следующей строки кода. Есть случаи, когда мы должны делать запросы к URL-адресам, а они не полагаются друг на друга. В этом сценарии мы не хотим ждать результата одного запроса для выполнения других запросов. Поэтому мы делаем асинхронные запросы.
Библиотека Guzzle 6
Guzzle — это HTTP-клиент на PHP, который помогает отправлять HTTP-запросы. Эти методы могут использоваться для отправки асинхронных HTTP-запросов.
- RequestAsync,
- SendAsync,
- GetAsync,
- HeadAsync,
- PutAsync,
- PostAsync,
- DeleteAsync,
- patchAsync
Скачайте пакет guzzle . Его можно установить через composer .
php composer.phar require guzzlehttp/guzzle:~6.0
composer require guzzlehttp/guzzle:~6.0
Включите файл autoload.php в часть кода сценария, чтобы он загружал все классы и методы.
getAsync('http://localhost') ->then(function ($response) < echo '10'; >), $client->getAsync('http://www.google.com') ->then(function ($response) < echo '20'; >), $client->getAsync('http://localhost') ->then(function ($response) < echo '30'; >), $client->getAsync('http://localhost') ->then(function ($response) < echo '40'; >), $client->getAsync('http://localhost') ->then(function ($response) < echo '50'; >), $client->getAsync('http://localhost') ->then(function ($response) < echo '60'; >), $client->getAsync('http://localhost') ->then(function ($response) < echo '70'; >), ]; $results = GuzzleHttp\Promise\unwrap($promises); // Please wait for a while to complete // the requests(some of them may fail) $results = GuzzleHttp\Promise\settle( $promises)->wait(); print "finish/over." . PHP_EOL; ?>
В приведенный выше код включается файл autoload.php , а затем создается клиентский объект GuzzleHttp, который сохраняется в переменной client , и для каждого запроса Http используется метод getAsync() с URL-адресом.
Запрос, получивший первый ответ, выведет номер. Порядок запроса не имеет значения.
Асинхронные HTTP-запросы с использованием Promise
При использовании Promise результат асинхронной операции представляет собой Promise (специальный объект, который содержит своё состояние). Асинхронные запросы используются для неблокирующих операций HTTP. Когда асинхронные HTTP-запросы отправляют Promise, то возвращается состояние.
Выполним запрос с помощью HTTPlug:
$request = $messageFactory->createRequest( 'GET', 'http://php-http.org'); $Promise = $client->sendAsyncRequest ($request); echo 'Неблокирующий!';
«Promise», который возвращается из вышеупомянутого, реализует http\Promise\Promise .
$promise->wait() будет ожидать получения ответа
try < $response = $promise->wait(); > catch (\Exception $exception) < echo $exception->getMessage(); >
Вместо ожидания мы можем выполнять шаги асинхронно. Для этого нужно вызвать метод then с двумя аргументами.
- Функция обратного вызова, которая будет выполнена, если запрос окажется успешным.
- Функция обратного вызова, которая будет выполнена, если запрос приведет к ошибке.
// Success Callback function (ResponseInterface $response) < echo 'New response!'; // Write status code to the log file file_put_contents('responses.log', $response->getStatusCode() . "\n", FILE_APPEND); return $response; >, // Failure Callback function (\Exception $exception)
Параллелизм в Promise
Параллелизм означает одновременное выполнение нескольких вычислений. Обрабатка большого количества запросов одновременно может улучшить производительность. Для параллелизма мы должны использовать класс EveryPromise и генератор yield и, наконец, добавить wait() в конец программы.
getAsync( 'https://api.demo.com/v1/users?username=' . $user); > >)(); $eachPromise = new EachPromise($promises, [ // Number of concurrency 'concurrency' => 4, 'fulfilled' => function (Response $response) < if ($response->getStatusCode() == 200) < $user = json_decode( $response->getBody(), true); // processing response of the user > >, 'rejected' => function ($reason) < // handle promise rejected >]); $eachPromise->promise()->wait(); ?>
Многопоточные запросы с cURL
PHP как правило, может обрабатывать несколько запросов. Сначала мы запускаем первый и обрабатываем ответ, затем второй и третий и так далее. Но этот процесс медленный и требует много времени. Но предлагает функции curl_multi_ * для обработки любых asnyc-запросов.
$running = null; $mh = curl_multi_init(); $ch1 = curl_init(); curl_setopt($ch1, CURLOPT_URL, ‘https://endpoint.com’); // Other curl options… curl_multi_add_handle($mh, $ch1); $ch2 = curl_init(); curl_setopt($ch2, CURLOPT_URL, ‘https://endpoint.com’); // Other curl options… curl_multi_add_handle($mh, $ch2); do < curl_multi_exec($mh, $running); curl_multi_select($mh); >while ($running > 0); $r1 = curl_multi_getcontent($ch1); $r2 = curl_multi_getcontent($ch2); curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh);
Ответы собираются в переменных «r1» и «r2». С помощью этих функций cURL мы можем запускать запросы параллельно, чтобы сэкономить время и быстрее обрабатывать ответы.
PHP АСИНХРОННЫЙ ЗАПРОС
Асинхронные запросы в PHP представляют собой отправку нескольких запросов на сервер и получение ответов параллельно. Это позволяет увеличить скорость и производительность приложения, особенно при работе с большим количеством данных. Для отправки асинхронных запросов в PHP можно использовать библиотеки, такие как ReactPHP или Guzzle.
Рассмотрим пример использования библиотеки Guzzle для отправки асинхронных запросов. Для начала необходимо установить Guzzle с помощью утилиты Composer:
composer require guzzlehttp/guzzle
Затем необходимо создать экземпляр Guzzle и добавить несколько запросов:
$client = new \GuzzleHttp\Client();
$promises = [];
$promises[‘request_1’] = $client->getAsync(‘https://jsonplaceholder.typicode.com/todos/1’);
$promises[‘request_2’] = $client->getAsync(‘https://jsonplaceholder.typicode.com/todos/2’);
$promises[‘request_3’] = $client->getAsync(‘https://jsonplaceholder.typicode.com/todos/3’);
Затем отправляем запросы параллельно:
И обрабатываем полученные результаты:
foreach ($results as $key => $value) echo $key . ‘: ‘ . $value->getBody() . ‘
‘;
>
Таким образом, мы отправляем три асинхронных запроса и получаем ответы параллельно, что увеличивает скорость и производительность нашего приложения.
Swoole ускоряем php в десятки раз, асинхронный php
Роман Пронский, “Асинхронный PHP”
Асинхронный php — Антон Шабовта (Onliner)
ReactPHP: асинхронный неблокирующий сервер на PHP на простых примерах
Aсинхронный PHP / Антон Шабовта (Onliner)
КАК БЕЗ ПЕРЕЗАГРУЗКИ СТРАНИЦЫ СДЕЛАТЬ ЗАПРОС
Открытое собеседование PHP Point #1 / Валентин Удальцов vs Патрик Фельдеш
Асинхронность в PHP: ожидания и реальность // Демо-занятие курса «PHP Developer. Professional»
Aсинхронный PHP / Антон Шабовта (Onliner)