Reputation: 2387
I have a PHP application that fetches prices from various sources. On every execution, it's loading from over 20 API endpoints using Guzzle. Due to the load time of each call, it's taking 10-30 sec per execution cycle. If I can make all the calls in parallel, I can cut it down to less than 5 seconds.
What's the easiest way to make parallel API calls in PHP?
Upvotes: 1
Views: 3608
Reputation: 160
Try to convert the API calls to be done using commands, for example: If you have 20 calls,
exec('php apiCall_1.php >> "./log.txt" &')
exec('php apiCall_2.php >> "./log.txt" &')
.
.
.
.
exec('php apiCall_20.php >> "./log.txt" &')
Notes:
1- All of those commands will be fired in async (do not forget to add the '&' at the end of each command to fire it, so it will not wait for the response).
2- Each command normally will store the result(which is fetched from the server) in DB collection/table.
3- Along with that, you have to write a method that keeps looking for the result if it's inserted to DB or not, so you can take it and send it back to your api consumer.
Upvotes: 2
Reputation: 6908
You're probably doing the wrong thing. These requests should probably be made at a regular interval in the background and the data be cached.
What you're trying to do is possible by leveraging non-blocking I/O. Curl offers this with curl_multi
, which is available in Guzzle. But there are also other libraries implementing HTTP clients based on non-blocking I/O without a dependency on ext-curl
, such as Artax.
Artax is based on Amp, which provides the basic primitives like the event loop and promises. You can start multiple requests and then wait for the set of promises.
$client = new Amp\Artax\DefaultClient;
$promises = [];
foreach ($urls as $url) {
$promises[$url] = Amp\call(function () use ($client, $url) {
// "yield" inside a coroutine awaits the resolution of the promise
// returned from Client::request(). The generator is then continued.
$response = yield $client->request($url);
// Same for the body here. Yielding an Amp\ByteStream\Message
// buffers the entire message.
$body = yield $response->getBody();
return $body;
});
}
$responses = Amp\Promise\wait(Amp\Promise\all($promises));
Upvotes: 3