PHP curl同時ベストプラクティスコード共有

5221 ワード

本文は2種類の具体的な実現方法を検討し、異なる方法に対して簡単な性能比較を行う.
1.経典のcURLの同時メカニズムとその存在する問題経典のcURLの実現メカニズムはネット上で簡単に見つけることができて、例えばPHPオンラインマニュアルの以下の実現方式を参考にします:
 
  
function classic_curl($urls, $delay) {
$queue = curl_multi_init();
$map = array();

foreach ($urls as $url) {
// create cURL resources
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);

// add handle
curl_multi_add_handle($queue, $ch);
$map[$url] = $ch;
}

$active = null;

// execute the handles
do {
$mrc = curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active > 0 && $mrc == CURLM_OK) {
if (curl_multi_select($queue, 0.5) != -1) {
do {
$mrc = curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}

$responses = array();
foreach ($map as $url=>$ch) {
$responses[$url] = callback(curl_multi_getcontent($ch), $delay);
curl_multi_remove_handle($queue, $ch);
curl_close($ch);
}

curl_multi_close($queue);
return $responses;
}

まずすべてのURLをコンカレントキューに押し込む、その後コンカレントプロセスを実行し、すべての要求が受信後にデータの解析などの後続処理を行う.実際の処理過程では、ネットワーク伝送の影響で、一部のURLの内容は他のURLよりも優先するが、古典的なcURLが同時に最も遅いそのURLが戻ってから処理を開始しなければならず、待つことはCPUの空きと浪費を意味する.URLキューが短いと、このような空きや無駄は許容できる範囲にあるが、キューが長いと、このような待ちや無駄は許容できない.
2.改良されたRolling cURL同時方式
よく分析すると、古典的なcURLは同時に最適化の空間が存在し、最適化の方式はあるURLの要求が終わった後にできるだけ早くそれを処理し、処理しながら他のURLの戻りを待つのではなく、その最も遅いインタフェースの戻りを待ってから処理を開始するなどの作業を待つので、CPUの空きと浪費を避けることができる.余計なことは言わないで、以下に具体的な実現を貼ります:
 
  
function rolling_curl($urls, $delay) {
$queue = curl_multi_init();
$map = array();

foreach ($urls as $url) {
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);

curl_multi_add_handle($queue, $ch);
$map[(string) $ch] = $url;
}

$responses = array();
do {
while (($code = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;

if ($code != CURLM_OK) { break; }

// a request was just completed -- find out which one
while ($done = curl_multi_info_read($queue)) {

// get the info and content returned on the request
$info = curl_getinfo($done['handle']);
$error = curl_error($done['handle']);
$results = callback(curl_multi_getcontent($done['handle']), $delay);
$responses[$map[(string) $done['handle']]] = compact('info', 'error', 'results');

// remove the curl handle that just completed
curl_multi_remove_handle($queue, $done['handle']);
curl_close($done['handle']);
}

// Block for data in / output; error handling is done by curl_multi_exec
if ($active > 0) {
curl_multi_select($queue, 0.5);
}

} while ($active);

curl_multi_close($queue);
return $responses;
}

3.2つの同時実装のパフォーマンス比較
改善前後の性能比較試験はLINUXホスト上で行い、試験時に使用する同時キューは以下の通りである.
http://item.taobao.com/item.htm?id=14392877692
http://item.taobao.com/item.htm?id=16231676302
http://item.taobao.com/item.htm?id=17037160462
http://item.taobao.com/item.htm?id=5522416710
http://item.taobao.com/item.htm?id=16551116403
http://item.taobao.com/item.htm?id=14088310973

実験設計の原則と性能試験結果のフォーマットを簡単に説明する:結果の信頼性を保証するために、各グループの実験は20回繰り返し、単一の実験では、同じインタフェースURLの集合を与え、Classic(古典的な同時機構を指す)とRolling(改善された同時機構を指す)の2種類の同時機構の時間(秒単位)をそれぞれ測定し、時間の短い者が勝つ(Winner)節約時間(Excellence、秒単位)と性能向上率(Excel.%)を計算する.実験の簡単さをできるだけ真実の要求に近づけるために、結果を返す処理では単純な正規表現マッチングを行っただけで、他の複雑な操作は行わなかった.また、結果処理のコールバックが性能比較試験結果に及ぼす影響を決定するために、usleepシミュレーションの現実における比較的責任のあるデータ処理ロジック(抽出、分詞、ファイルやデータベースへの書き込みなど)を用いることができる.
パフォーマンステストで使用されるコールバック関数は、次のとおりです.
 
  
function callback($data, $delay) {
preg_match_all('/

(.+)/iU', $data, $matches);
usleep($delay);
return compact('data', 'matches');
}


データ処理のコールバックに遅延がない場合:Rolling Curlはやや優れているが、性能向上効果は明らかではない.
データ処理のコールバック遅延は5ミリ秒:Rolling Curlが完勝し、性能は40%程度向上した.
上記の性能比較により、URLキューの同時処理を行うアプリケーションシーンでは、Rolling cURLがより選択されるべきであり、同時量が非常に大きい(1000+)場合、同時キューの最大長を制御することができる.例えば、20は、1つのURLが戻って処理が完了するたびに、要求されていないURLをキューに追加すると、書かれたコードがより丈夫になる.合併数が大きすぎて詰まったり崩れたりすることはない.実装の詳細については、以下を参照してください.http://code.google.com/p/rolling-curl/