Я могу выполнять одиночные запросы с использованием Guzzle, и до сих пор я очень доволен производительностью Guzzle, я прочитал в Guzzle API что-то о MultiCurl и Batching.
Может ли кто-нибудь объяснить мне, как делать несколько запросов одновременно? Async если возможно. Я не знаю, что это значит с MultiCurl. Синхронизация также не будет проблемой. Я просто хочу делать несколько запросов одновременно или очень близко (короткое время).
Из документов: http://guzzle3.readthedocs.org/http-client/client.html#sending-requests-in-parallel
Для простого в использовании решения, которое возвращает хеш отображения объектов запроса на ответ или ошибку, см. http://guzzle3.readthedocs.org/batching/batching.html#batching
Краткий пример:
<?php $client->send(array( $client->get('http://www.example.com/foo'), $client->get('http://www.example.com/baz'), $client->get('http://www.example.com/bar') ));
Обновление, связанное с новым GuzzleHttp guzzlehttp / guzzle
Параллельные / параллельные вызовы теперь выполняются несколькими различными способами, включая Promises. Параллельные запросы
Старый способ передачи массива RequestInterfaces больше не будет работать.
См. Пример здесь
$newClient = new \GuzzleHttp\Client(['base_uri' => $base]); foreach($documents->documents as $doc){ $params = [ 'language' =>'eng', 'text' => $doc->summary, 'apikey' => $key ]; $requestArr[$doc->reference] = $newClient->getAsync( '/1/api/sync/analyze/v1?' . http_build_query( $params) ); } $time_start = microtime(true); $responses = \GuzzleHttp\Promise\unwrap($requestArr); //$newClient->send( $requestArr ); $time_end = microtime(true); $this->get('logger')->error(' NewsPerf Dev: took ' . ($time_end - $time_start) );
Обновление : как было предложено в комментариях и задано @ sankalp-tambe, вы также можете использовать другой подход, чтобы избежать того, что набор одновременных запросов с отказом не будет возвращать все ответы.
Хотя варианты, предлагаемые с помощью пула, возможны, я по-прежнему предпочитаю обещания.
Примером с обещаниями является использование методов sed и wait вместо разворота.
Отличие от приведенного выше примера
$responses = \GuzzleHttp\Promise\settle($requestArr)->wait();
Я привел полный пример ниже для справки о том, как обрабатывать $ response тоже.
require __DIR__ . '/vendor/autoload.php'; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Promise as GuzzlePromise; $client = new GuzzleClient(['timeout' => 12.0]); // see how i set a timeout $requestPromises = []; $sitesArray = SiteEntity->getAll(); // returns an array with objects that contain a domain foreach ($sitesArray as $site) { $requestPromises[$site->getDomain()] = $client->getAsync('http://' . $site->getDomain()); } $results = GuzzlePromise\settle($requestPromises)->wait(); foreach ($results as $domain => $result) { $site = $sitesArray[$domain]; $this->logger->info('Crawler FetchHomePages: domain check ' . $domain); if ($result['state'] === 'fulfilled') { $response = $result['value']; if ($response->getStatusCode() == 200) { $site->setHtml($response->getBody()); } else { $site->setHtml($response->getStatusCode()); } } else if ($result['state'] === 'rejected') { // notice that if call fails guzzle returns is as state rejected with a reason. $site->setHtml('ERR: ' . $result['reason']); } else { $site->setHtml('ERR: unknown exception '); $this->logger->err('Crawler FetchHomePages: unknown fetch fail domain: ' . $domain); } $this->entityManager->persist($site); // this is a call to Doctrines entity manager }
-require __DIR__ . '/vendor/autoload.php'; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Promise as GuzzlePromise; $client = new GuzzleClient(['timeout' => 12.0]); // see how i set a timeout $requestPromises = []; $sitesArray = SiteEntity->getAll(); // returns an array with objects that contain a domain foreach ($sitesArray as $site) { $requestPromises[$site->getDomain()] = $client->getAsync('http://' . $site->getDomain()); } $results = GuzzlePromise\settle($requestPromises)->wait(); foreach ($results as $domain => $result) { $site = $sitesArray[$domain]; $this->logger->info('Crawler FetchHomePages: domain check ' . $domain); if ($result['state'] === 'fulfilled') { $response = $result['value']; if ($response->getStatusCode() == 200) { $site->setHtml($response->getBody()); } else { $site->setHtml($response->getStatusCode()); } } else if ($result['state'] === 'rejected') { // notice that if call fails guzzle returns is as state rejected with a reason. $site->setHtml('ERR: ' . $result['reason']); } else { $site->setHtml('ERR: unknown exception '); $this->logger->err('Crawler FetchHomePages: unknown fetch fail domain: ' . $domain); } $this->entityManager->persist($site); // this is a call to Doctrines entity manager }
-require __DIR__ . '/vendor/autoload.php'; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Promise as GuzzlePromise; $client = new GuzzleClient(['timeout' => 12.0]); // see how i set a timeout $requestPromises = []; $sitesArray = SiteEntity->getAll(); // returns an array with objects that contain a domain foreach ($sitesArray as $site) { $requestPromises[$site->getDomain()] = $client->getAsync('http://' . $site->getDomain()); } $results = GuzzlePromise\settle($requestPromises)->wait(); foreach ($results as $domain => $result) { $site = $sitesArray[$domain]; $this->logger->info('Crawler FetchHomePages: domain check ' . $domain); if ($result['state'] === 'fulfilled') { $response = $result['value']; if ($response->getStatusCode() == 200) { $site->setHtml($response->getBody()); } else { $site->setHtml($response->getStatusCode()); } } else if ($result['state'] === 'rejected') { // notice that if call fails guzzle returns is as state rejected with a reason. $site->setHtml('ERR: ' . $result['reason']); } else { $site->setHtml('ERR: unknown exception '); $this->logger->err('Crawler FetchHomePages: unknown fetch fail domain: ' . $domain); } $this->entityManager->persist($site); // this is a call to Doctrines entity manager }
Этот примерный код был первоначально размещен здесь .