前の記事 ≪:2008年2月21日 管理人のブックマーク
次の記事 ≫:超クールなカレンダー型日付入力補助用JSライブラリ

マッシュアップに必須!PHPで複数APIを同時に叩いて超高速化するサンプル

2008年02月22日-はてなブックマーク

スポンサード リンク
[PR] 英単語を忘却曲線アプリを使って超効率よく記憶する方法
phpied.com Blog Archive Simultaneuos HTTP requests in PHP with cURL
The basic idea of a Web 2.0-style "mashup" is that you consume data from several services, often from different providers and combine them in interesting ways.

マッシュアップに必須!PHPで複数APIを同時に叩いて超高速化するサンプル。
通常、PHPでAPIにアクセスする場合、例えば、Yahoo!検索APIとはてなブックマークのRSSを取得してマッシュアップする場合は次の図のようになります。



ただ、この方式だと、Yahoo!検索APIにリクエストし、その結果を待ちます。
そして、そこからはてなブックマークにリクエストして、更にその結果を待つという、比較的時間のかかる処理が必要です。

(1)に3秒、(2)に2秒かかったとすると、合計5秒もかかります。

そこで今回のサンプルを使うと、Yahoo!検索APIとはてなのRSSに同時にアクセスすることが可能です。



両方を同時に叩くので当然、効率がよいです。
アクセス先の数が2個ではなく、もっと多くなった際、その差はより顕著ですね。

紹介されているmultiRequest関数

<?php

function multiRequest($data, $options = array()) {

  
// array of curl handles
  
$curly = array();
  
// data to be returned
  
$result = array();

  
// multi handle
  
$mh = curl_multi_init();

  
// loop through $data and create curl handles
  // then add them to the multi-handle
  
foreach ($data as $id => $d) {

    
$curly[$id] = curl_init();

    
$url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
    
curl_setopt($curly[$id], CURLOPT_URL,            $url);
    
curl_setopt($curly[$id], CURLOPT_HEADER,         0);
    
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);

    
// post?
    
if (is_array($d)) {
      if (!empty(
$d['post'])) {
        
curl_setopt($curly[$id], CURLOPT_POST,       1);
        
curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
      }
    }

    
// extra options?
    
if (!empty($options)) {
      
curl_setopt_array($curly[$id], $options);
    }

    
curl_multi_add_handle($mh, $curly[$id]);
  }

  
// execute the handles
  
$running = null;
  do {
    
curl_multi_exec($mh, $running);
  } while(
$running > 0);

  
// get content and remove handles
  
foreach($curly as $id => $c) {
    
$result[$id] = curl_multi_getcontent($c);
    
curl_multi_remove_handle($mh, $c);
  }

  
// all done
  
curl_multi_close($mh);

  return
$result;
}

?>

(注意) curl_multi_exec の呼び出し方が正しくない可能性があるので、PHPマニュアルのコードも参考にして下さい

次のようにURLの配列を渡してデータを一括取得できます。

<?php

$data = array(
  
'http://search.yahooapis.com/VideoSearchService/V1/videoSearch?appid=YahooDemo&query=Pearl+Jam&output=json',
  
'http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Pearl+Jam&output=json',
  
'http://search.yahooapis.com/AudioSearchService/V1/artistSearch?appid=YahooDemo&artist=Pearl+Jam&output=json'
);
$r = multiRequest($data);

echo
'<pre>';
print_r($r);
内部では、curl_multi_*関数を使っているようで、これはPHP5から使えるcurl用の関数みたい。
実際にmicrotime関数によってベンチマークを取ってみたところ、同時アクセスの場合、0.74...秒という結果が得られました。

URLを1個1個取得するプログラムをcurlで試したところ、1.67...秒かかりました。
今回のサンプルではおよそ2倍ちょっとの速度差が出ました。

APIのサーバの重さやアクセス先の数などによってもこの結果は大きく違ってくるはずです。
XML-RPCやAtomAPI、POSTによってAPIを叩かなくてはいけない場合もあるので全てこれで対応可能というわけではありません。
ですが、REST-APIを叩く場合には使えるので、マッシュアップを行う際に必須といってもよさそうですね。
スポンサード リンク

By.KJ : 2008年02月22日 07:10 livedoor Readerで購読 Twitterに投稿

間違いの指摘をしていただける方はメール、あるいはTwitter/FBでお願いします(クリック)