我可以使用Guzzle执行单个请求,到目前为止,我对Guzzle的性能非常满意,然而,我在Guzzle中读到了一些关于MultiCurl和批处理的内容。
有人能给我解释一下如何同时发出多个请求吗?如果可能,请使用异步。我不知道这是不是他们对MultiCurl的意思。同步也不是问题。我只想同时做多个请求,或者非常接近(短时间)。
发布于 2013-10-26 05:00:19
来自文档: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')
));
发布于 2015-09-24 07:18:00
与新的GuzzleHttp guzzlehttp/guzzle相关的更新
并发/并行调用现在通过几种不同的方法运行,包括Promises。Concurrent Requests
传递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的询问,您还可以使用不同的方法来避免一组失败的并发请求不会返回所有响应。
虽然Pool建议的选项是可行的,但我仍然更喜欢promises。
promises的一个例子是使用settle和wait方法,而不是解包。
与上面示例的区别是
$responses = \GuzzleHttp\Promise\settle($requestArr)->wait();
我已经在下面创建了一个完整的示例,以供参考如何处理$responses。
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
}
这个示例代码最初发布在here上。
发布于 2019-08-01 13:41:45
Guzzy6.0使得发送多个异步请求变得非常容易。
有多种方法可以做到这一点。
您可以创建异步请求,并将生成的promises添加到单个数组中,然后使用settle()
方法获得结果,如下所示:
$promise1 = $client->getAsync('http://www.example.com/foo1');
$promise2 = $client->getAsync('http://www.example.com/foo2');
$promises = [$promise1, $promise2];
$results = GuzzleHttp\Promise\settle($promises)->wait();
现在,您可以遍历这些结果,并使用GuzzleHttpPromiseall
或GuzzleHttpPromiseeach
获取响应。有关更多详细信息,请参阅this article。
如果您要发送的请求数不确定(这里是5个),您可以使用GuzzleHttp/Pool::batch()
。下面是一个示例:
$client = new Client();
// Create the requests
$requests = function ($total) use($client) {
for ($i = 1; $i <= $total; $i++) {
yield new Request('GET', 'http://www.example.com/foo' . $i);
}
};
// Use the Pool::batch()
$pool_batch = Pool::batch($client, $requests(5));
foreach ($pool_batch as $pool => $res) {
if ($res instanceof RequestException) {
// Do sth
continue;
}
// Do sth
}
https://stackoverflow.com/questions/19520185
复制相似问题