Just as a complement to the @ViniciusZaramella answer, where he cites the
requests from Guzzle\Http
.
Explanation on Guzzle's Asynchronism
As for the asynchronism of the Guzzle requests, I noticed that the same, when using the Pool
class, actually sends several requests at once in background
, thus having their responses asynchronously.
In case, if we made a request with Guzzle
, normally, without using Pool
, within a for 0 to 200, the request would wait for the response of the other to make a request.
Example:
$guzzle = new GuzzleHttp\Client;
for ($i = 0; $i < 200; $i++)
{
$guzzle->get('http://httpbin.org/get', ['query' => ['i' => $i]]);
}
In the case of Pool
, the requests are sent "at once" - according to the configuration you set to concurrency
, which is the number of requests made at a time in the queue.
$requests = function () {
$guzzle = new GuzzleHttp\Client;
for ($i = 0; $i < 200; $i++)
{
yield $guzzle->get('http://httpbin.org/get', ['query' => ['i' => $i]]);
}
};
$pool = new Pool($guzzle, $requests(), [
'concurrency' => 50, // envia de 30 em 30,
'rejected' => function ($exception, $index)
{
},
'fulfilled' => function ($response, $index)
{
}
]);
$poll->promise()->wait();
I performed similar tests on both cases. The result was that, in the case similar to the first example, it took 45 to 50 seconds for a request (enough to give that PHP time-out error). In the second case, only 5 to 7 seconds were used at run time.
So, it really is an effective method.
Other Asynchronism
Before Vinicius's response was published, I had found on the internet to make asynchronous requests with PHP. However, by performing such an operation, PHP will not wait for the response , but will only make the request while the code will run normally until the end.
function async_request($method, $url, $params, array $headers = [])
{
$method = strtoupper($method);
$sendData = in_array($method, array('PUT', 'POST'));
$data = http_build_query($params);
$parts = parse_url($url) + [
'port' => 80,
'path' => '/',
];
$headers += [
'Content-Type' => 'application/x-www-form-urlencoded',
'Host' => $parts['host'],
'Content-Length' => !$sendData ? 0 : strlen($data),
'Connection' => 'Close'
];
$path = !$sendData ? $parts['path'] . '?' . $data : $parts['path'];
$output_header = sprintf('%s %s HTTP/1.1', $method, $path) . "\r\n";
foreach ($headers as $name => $value)
{
foreach((array) $value as $v)
{
$output_header .= "$name: $v\r\n";
}
}
$output_header .= "\r\n";
$handle = @fsockopen($parts['host'], $parts['port'], $_errno, $_errstr, 30);
if ($handle === false)
{
throw new \RuntimeException($_errstr);
}
fwrite($handle, $output_header);
if ($sendData) fwrite($handle, $data);
fclose($handle);
return $output_header;
}
You can test this function as follows:
#index.php
assync_request('GET', 'http://localhost/target.php', []);
echo 'terminou';
#target.php
sleep(5);
file_put_contents('gato.txt', "Meow!!!\n\n", FILE_APPEND);
When you make the request, you will notice that the word 'terminou'
is displayed immediately. And after 5 seconds, the gato.txt
file will be created. This is because php ran a socket in backgroud, which was responsible for the target.php
request.
This was the idea I had initially about asynchronism, but anyway the answer from @ ViniciusZaramella answered me better.