How to make asynchronous http requests in php
Asynchronous HTTP request helps us to process HTTP requests using non-blocking input or output, in different threads. «PHP / Curl: HEAD Request takes a long time on some sites» describes how to do a request using PHP/Curl If you want to trigger the request, and not hold up the script at all, there are a few ways, of varying complexities.. Execute the HTTP request as a background process, php execute a background process — basically you would execute something like — this will be platform specific, and you have to be really careful about escaping parameters to the command Executing a PHP script in the background — basically the same as the UNIX process method, but executing a PHP script rather than a shell command Have a «job queue», using a database (or something like beanstalkd which is likely overkill).
How to make asynchronous HTTP requests in PHP ?
Asynchronous HTTP request helps us to process HTTP requests using non-blocking input or output, in different threads. Some refer to it as COMET capabilities. The main use of Asynchronous HTTP requests is when the client is requesting the server for a late response. A common example is an AJAX chat client where we push or pull from both the client and the server. These scenarios block the client for quiet a long time on the server’s socket waiting for a new message.
PHP serves requests synchronously. It means that each line of code executes in the synchronous manner of the script. After getting the result from one line it executes next line or wait for the result before jumping to the execution of the next line of code. There are cases where we are supposed to make requests to URLs and they do not rely on each other. In this scenario we do not want to wait for the result from one request to execute other requests. Therefore, we make asynchronous requests.
Guzzle 6: Guzzle is a PHP HTTP client helps to send the HTTP requests.These methods can be used to send the asynchronous HTTP requests.
- RequestAsync,
- SendAsync,
- GetAsync,
- HeadAsync,
- PutAsync,
- PostAsync,
- DeleteAsync,
- patchAsync
Download Guzzle php package.Can be installed through composer.
php composer.phar require guzzlehttp/guzzle:~6.0
composer require guzzlehttp/guzzle:~6.0
Please include the “autoload” file in the script part of the code so that it loads all the classes and methods.
Как делать асинхронные 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 мы можем запускать запросы параллельно, чтобы сэкономить время и быстрее обрабатывать ответы.