我在我的PHP应用程序中使用cURL连接到RESTful API。但是,我刚刚发现我没有并行化我的cURL连接,因此执行几个连续的连接会导致最终用户的延迟时间过长。
之前我没有使用curl_multi
,在阅读完文档后我有点不知所措。我怎样才能最好地重构以下代码以利用curl_multi
的并行化?
编辑:我忘了提到我开源了这里使用的API。这些是我自己的Directed Edge PHP bindings。所以,如果您愿意,也可以将您的帮助合并到GitHub上的代码中,您将被列为贡献者。
以下是我在客户端代码中所做的一个示例:
// Get 100 goal recommendations from Directed Edge
$de = new DirectedEdgeRest();
$item = "user".$uid;
$limit = 100;
$tags = "goal";
$recommendedGoals = $de->getRecommended($item, $tags, $limit);
// Get 100 interest recommendations from Directed Edge
$de = new DirectedEdgeRest();
$item = "user".$uid;
$limit = 100;
$tags = "interest";
$recommendedInterests = $de->getRecommended($item, $tags, $limit);
以下是DirectedEdgeRest()
/**
* Returns array of recommended result IDs for an item
* @param string $item Item, e.g. "Miles%20Davis"
* @param string $tags Tags as comma delimited string, e.g. "product,page"
* @param int $limit Limit for max results
*
* @return array Recommended result IDs
*/
public function getRecommended($item, $tags, $limit)
{
// Connect to Directed Edge and parse the returned XML
$targeturl = self::buildURL($item, 'recommended', $tags, $limit, 'true');
$response = self::getCurlResponse($targeturl);
$xml = self::parseXML($response);
// Iterate through the XML and place IDs into an array
foreach($xml->item->recommended as $recommended) {
$recommendedResults[] = filter_var($recommended, FILTER_SANITIZE_NUMBER_INT);
}
return $recommendedResults;
}
/**
* Builds URL for cURL
* @param string $item Item, e.g. "Miles%20Davis"
* @param string $type Type of API request: either "related" or "recommended"
* @param string $tags Tags as comma delimited string, e.g. "product,page"
* @param int $limit Limit for max results
* @param string $exclude "true" if you want to exclude linked, "false" otherwise
*
* @return string The target URL
*/
private function buildURL($item, $type, $tags, $limit, $exclude)
{
$targeturl = DE_BASE_URL;
$targeturl .= $item; // Item
$targeturl .= "/" . $type; // Type
$targeturl .= "?tags=" . $tags; // Tags
$targeturl .= "&maxresults=" . $limit; // Limit
$targeturl .= "&excludeLinked=" . $exclude; // Exclude
return $targeturl;
}
/**
* Returns the cURL response given a target URL
* @param string $targeturl The target URL for cURL
*
* @return string cURL Response
*/
private function getCurlResponse($targeturl)
{
$ch = curl_init($targeturl);
curl_setopt($ch, CURLOPT_POST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
答案 0 :(得分:1)
在你的问题之前,我没有意识到curl_multi
,这是一个非常奇怪的(对于PHP)界面。
看起来有一个Hello World example in the curl_multi_init documentation
// create both cURL resources
$ch1 = curl_init();
$ch2 = curl_init();
// set URL and other appropriate options
curl_setopt($ch1, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/");
curl_setopt($ch2, CURLOPT_HEADER, 0);
//create the multiple cURL handle
$mh = curl_multi_init();
//add the two handles
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
$running=null;
//execute the handles
do {
usleep(10000);
curl_multi_exec($mh,$running);
} while ($running > 0);
//close the handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
我从那开始。
答案 1 :(得分:0)
如果有人感兴趣,请按照以下方式重构代码以使用curl_multi
。如果这一切看起来很酷,或者你能做得更好,那么请contribute to the bindings!
class DirectedEdgeRest
{
/**
* Gets multiple simultaneous recommendations from Directed Edge
* @param array $queryArray Array of the form array(0 => (array('item' => (string) $item, 'tags' => (string) $tags, 'limit' => (int) $limit))
*
* @return array Multi-dimensional array containing responses to
* queries in the order they were passed in the array
*/
public function getMultiRecommended($queryArray)
{
$targetUrls = array();
foreach($queryArray as $query) {
$targeturl = self::buildURL($query['item'], 'recommended', $query['tags'], $query['limit'], 'true');
$targetUrls[] = $targeturl;
}
$responses = self::getMultiCurlResponses($targetUrls);
$xmlArray = array();
foreach($responses as $response) {
$xmlArray[] = self::parseXML($response);
}
$count = count($xmlArray);
// Iterate through the XML and place IDs into an array
for($i = 0; $i < $count; $i++) {
foreach($xmlArray[$i]->item->recommended as $recommended) {
$recommendedResults[$i][] = filter_var($recommended, FILTER_SANITIZE_NUMBER_INT);
}
}
return $recommendedResults;
}
/**
* Returns the cURL responses given multiple target URLs
* @param array $targetUrls Array of target URLs for cURL
*
* @return array cURL Responses
*/
private function getMultiCurlResponses($targetUrls)
{
// Cache the count
$count = count($targetUrls);
// Create the multiple cURL handles
for($i = 0; $i < $count; $i++) {
$ch[$i] = curl_init($targetUrls[$i]);
curl_setopt($ch[$i], CURLOPT_POST, FALSE);
curl_setopt($ch[$i], CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, TRUE);
}
// Initialize the multiple cURL handle
$mh = curl_multi_init();
// Add the handles to the curl_multi handle
for($i = 0; $i < $count; $i++) {
curl_multi_add_handle($mh, $ch[$i]);
}
$running=null;
// Execute the handles
do {
curl_multi_exec($mh,$running);
} while ($running > 0);
$responses = array();
// Remove the handles and return the response
for($i = 0; $i < $count; $i++) {
curl_multi_remove_handle($mh, $ch[$i]);
$responses[$i] = curl_multi_getcontent($ch[$i]);
}
// Close the multiple cURL handle
curl_multi_close($mh);
return $responses;
}
}
$uid = 3;
$de = new DirectedEdgeRest();
$query['item'] = "user".$uid;
$query['limit'] = 10;
$query['tags'] = "goal";
$queryArray[0] = $query;
$query['tags'] = "question";
$queryArray[1] = $query;
$recommended = $de->getMultiRecommended($queryArray);
echo '<pre>';
var_dump($recommended);
// Outputs...
array(2) {
[0]=>
array(10) {
[0]=>
string(3) "141"
[1]=>
string(2) "64"
[2]=>
string(2) "37"
[3]=>
string(2) "65"
[4]=>
string(2) "63"
[5]=>
string(1) "7"
[6]=>
string(2) "78"
[7]=>
string(1) "9"
[8]=>
string(2) "30"
[9]=>
string(2) "10"
}
[1]=>
array(10) {
[0]=>
string(2) "97"
[1]=>
string(3) "125"
[2]=>
string(3) "133"
[3]=>
string(3) "127"
[4]=>
string(3) "101"
[5]=>
string(3) "134"
[6]=>
string(2) "69"
[7]=>
string(2) "80"
[8]=>
string(2) "19"
[9]=>
string(3) "129"
}
}