curl_multiというのを見つけたので使ってみました.
外部APIを使う人にとっては必須かもしれません.

curl_multiとは

そのまんま,curlを複数並列に走らせるための関数です.
直列にすると待機時間が長いので,並列にリクエストを投げることで高速化が見込めます.

php5から使えるようです.

基本的な使い方

使い方としては次の通り.

  1. それぞれのリクエスト用のcurlを作成する
  2. curl_multiを一つ作り,そこにそれぞれのリクエスト用のcurlをセットする
  3. 実行!&リクエスト終了待ち
  4. それぞれのリクエスト用curl,curl_multiの両方をcloseする

php関数リファレンスよりサンプルコード
[php]
<?php
// cURL リソースを作成します
$ch1 = curl_init();
$ch2 = curl_init();

// URL およびその他適切なオプションを設定します。
curl_setopt($ch1, CURLOPT_URL, "http://lxr.php.net/");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/");
curl_setopt($ch2, CURLOPT_HEADER, 0);

// マルチ cURL ハンドルを作成します
$mh = curl_multi_init();

// ふたつのハンドルを追加します
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);

$active = null;
// ハンドルを実行します
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

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

// ハンドルを閉じます
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

?>
[/php]

ですが,こんなの面倒なので,ひとまとまりに関数化してしまいましょう

お手軽curl_multi

関数にまとめました.
arrayでurlを指定し,arrayでデータが返ってきます.
自分の環境ではなぜかよく失敗するので,失敗したurlをarrayで返すようにもしました.

[php]
public function fetchMultiUrl($urls, $timeout = 0, &$errorUrls = array()) {
$mh = curl_multi_init();

foreach ($urls as $key => $url) {
$conn[$key] = curl_init($url);
curl_setopt($conn[$key], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($conn[$key], CURLOPT_FAILONERROR, 1);
curl_setopt($conn[$key], CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($conn[$key], CURLOPT_MAXREDIRS, 3);

if ($timeout) {
curl_setopt($conn[$key], CURLOPT_TIMEOUT, $timeout);
}

curl_multi_add_handle($mh, $conn[$key]);
}

$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}

//データを取得
$res = array();
foreach ($urls as $key => $url) {
if (($err = curl_error($conn[$key])) == ”) {
$res[$key] = curl_multi_getcontent($conn[$key]);
} else {
$errorUrls[$key] = $url_list[$key];
}
curl_multi_remove_handle($mh, $conn[$key]);
curl_close($conn[$key]);
}
curl_multi_close($mh);

return $res;
}

[/php]

実際に使ったところ,30アクセスで40秒ぐらいだったのが10秒ぐらいまで高速化できました.
それほど難しくないですし,連続してAPIをたたく場合は便利です!

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>