PHPで複数の処理を実行したい場合、どうしても逐次処理となってしまいます。
例えば、5秒かかる処理が10個あった場合、5×10=50秒必要です。
それを、マルチスレッド(並列処理)で行えば5秒ですみます。
その方法を紹介します。情報元はこちらです。
例えば、5秒かかる処理が10個あった場合、5×10=50秒必要です。
それを、マルチスレッド(並列処理)で行えば5秒ですみます。
その方法を紹介します。情報元はこちらです。
PHPでマルチスレッド(バックグラウンド処理)を実現する方法 - EC studio 技術ブログ
<?php
//複数URLを同時に取得する
//@param array $url_list URLの配列
//@param int $timeout タイムアウト秒数 0だと無制限
//@return array 取得したソースコードの配列
function fetch_multi_url($url_list,$timeout=0) {
$mh = curl_multi_init();
foreach ($url_list as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
curl_setopt($conn[$i],CURLOPT_FAILONERROR,1);
curl_setopt($conn[$i],CURLOPT_FOLLOWLOCATION,1);
curl_setopt($conn[$i],CURLOPT_MAXREDIRS,3);
//SSL証明書を無視
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYHOST,false);
//タイムアウト
if ($timeout){
curl_setopt($conn[$i],CURLOPT_TIMEOUT,$timeout);
}
curl_multi_add_handle($mh,$conn[$i]);
}
//URLを取得
//すべて取得するまでループ
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
var_dump($mrc);
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);
}
}
if ($mrc != CURLM_OK) {
echo '読み込みエラーが発生しました:'.$mrc;
}
//ソースコードを取得
$res = array();
foreach ($url_list as $i => $url) {
if (($err = curl_error($conn[$i])) == '') {
$res[$i] = curl_multi_getcontent($conn[$i]);
} else {
echo '取得に失敗しました:'.$url_list[$i].'<br />';
}
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
}
curl_multi_close($mh);
return $res;
} ?>
//複数URLを同時に取得する
//@param array $url_list URLの配列
//@param int $timeout タイムアウト秒数 0だと無制限
//@return array 取得したソースコードの配列
function fetch_multi_url($url_list,$timeout=0) {
$mh = curl_multi_init();
foreach ($url_list as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
curl_setopt($conn[$i],CURLOPT_FAILONERROR,1);
curl_setopt($conn[$i],CURLOPT_FOLLOWLOCATION,1);
curl_setopt($conn[$i],CURLOPT_MAXREDIRS,3);
//SSL証明書を無視
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYHOST,false);
//タイムアウト
if ($timeout){
curl_setopt($conn[$i],CURLOPT_TIMEOUT,$timeout);
}
curl_multi_add_handle($mh,$conn[$i]);
}
//URLを取得
//すべて取得するまでループ
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
var_dump($mrc);
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);
}
}
if ($mrc != CURLM_OK) {
echo '読み込みエラーが発生しました:'.$mrc;
}
//ソースコードを取得
$res = array();
foreach ($url_list as $i => $url) {
if (($err = curl_error($conn[$i])) == '') {
$res[$i] = curl_multi_getcontent($conn[$i]);
} else {
echo '取得に失敗しました:'.$url_list[$i].'<br />';
}
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
}
curl_multi_close($mh);
return $res;
} ?>
このfetch_multi_url関数を元に本体は次のとおりにします。
<?php
header('Content-type:text/html; charset=UTF-8');
//並列実行したいPHP
$url_list = array(
'http://localhost/sleep.php?pid=1',
'http://localhost/sleep.php?pid=2',
'http://localhost/sleep.php?pid=3',
'http://localhost/sleep.php?pid=4',
);
//開始時間取得
$time = time();
//実行
$res = fetch_multi_url($url_list);
//結果出力
echo '実行結果:<pre>';
print_r($res);
echo '</pre>';
//実行時間
echo '--<br />time:'.(time() - $time).' sec';
?>
header('Content-type:text/html; charset=UTF-8');
//並列実行したいPHP
$url_list = array(
'http://localhost/sleep.php?pid=1',
'http://localhost/sleep.php?pid=2',
'http://localhost/sleep.php?pid=3',
'http://localhost/sleep.php?pid=4',
);
//開始時間取得
$time = time();
//実行
$res = fetch_multi_url($url_list);
//結果出力
echo '実行結果:<pre>';
print_r($res);
echo '</pre>';
//実行時間
echo '--<br />time:'.(time() - $time).' sec';
?>
sleep.phpは5秒待つだけのスクリプトです。
実行結果は、逐次処理なら20秒かかるところが5秒で処理がします。
ただし、私が現在構築している処理は1処理が数分から数十分かかる処理なので、処理が完了するまで応答がないのはブラウザタイムアウトとなる為、採用は見送っています。
ただ、今後使える関数なので掲載しておきます。
ちなみにPHP の cURL サポート機能を使用するには、--with-curl[=DIR] を付けて PHP をコンパイル しておく必要があります。
windowsの場合は、まずlibeay32.dll および ssleay32.dll が PATH の通った場所に存在する必要があります。
次に、php.ini内に次の行を追加します。
extension=libeay32.dll
extension=ssleay32.dll
extension=php_curl.dll
【WEB開発】コメントする