Description
Symfony version(s) affected
5.4.0
Description
Very often, I use the Symfony HttpClient to perform N requests on N URLs asynchronously. By doing so, the total time to complete the N requests is greatly decreased.
However, the same effect is not observed when the remote server does not respond. For instance, if the timeout is set to 5 seconds, performing 10 requests will take 50 seconds. I would expect it to take about 5 seconds, because the requests are made asynchronously.
I have added a script below to reproduce the issue. Please note that it is also reproduced if HttpClient::create is replaced by CurlHttpClient::create or NativeHttpClient::create. Also, it is not related to Symfony 5.4. I reproduce this with 5.3 and 6.0.
How to reproduce
<?php
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\Exception\TimeoutException;
use Symfony\Component\Stopwatch\Stopwatch;
require_once __DIR__.'/vendor/autoload_runtime.php';
$client = HttpClient::create();
$stopwatch = new Stopwatch();
$stopwatch->start('not parallel');
try {
$client->request('GET', 'http://10.255.255.1', ['timeout' => 5]);
} catch (TimeoutException) {
echo ".";
}
echo "\n".$stopwatch->stop('not parallel')."\n";
$stopwatch->start('parallel');
$requests = [];
for ($i = 0; $i < 10; $i++) {
$requests[] = $client->request('GET', 'http://10.255.255.1', ['timeout' => 5]);
}
foreach ($requests as $response) {
try {
$response->getContent();
} catch (TimeoutException) {
echo ".";
}
}
echo "\n".$stopwatch->stop('parallel')."\n";
The result is below:
.
default/not parallel: 6.00 MiB - 5008 ms
..........
default/parallel: 6.00 MiB - 50012 ms
The last value, 50 seconds, should be more like 5 seconds if the requests really happened asynchronously.
If I replace the unroutable IP with https://www.google.com I get:
default/not parallel: 6.00 MiB - 205 ms
default/parallel: 6.00 MiB - 108 ms
Possible Solution
@nicolas-grekas do you have an explanation for this behavior? I ask because of your inspiring talk on asynchronous HTTP requests using this component. Would you provide some guidance so I could help fixing this issue? Thanks a lot in advance!
Additional Context
No response