電子書籍の厳選無料作品が豊富!

現在、レンタルサーバ(コアサーバー)上でPHP5とmysqlでサイトへのアクセス数とサイト上の複数のリンク先へのクリック数のログを取得し、一日一回それらを一つのテーブルへ集計し、レポート表示させるプログラムを作成しました。

一日のログが少なかった頃は問題なく動いていたのですが、一日のログ数が10万を超えた辺りから集計処理がタイムアウトしてしまい、集計ができなくなってしまいました。

下記のようなイメージで集計プログラムとして動かしています。
ループ数は25,000回位です。
ループ中にはmysqlからの読み込みと書き込み処理を含んでおります。

$i = "0";
do{//サイト数だけループ
$cat_i = "0";
do{//カテゴリ数だけループ
$carrier = "0";
do{
$cl_i = "1";
do{
}while($cl_i < 21);
   $carrier = $carrier + 1;
         }while($carrier < 3);
$cat_i = $cat_i + 1;
}while($cat_i < $rows_cat);
$i = $i + 1;
}while($i < $rows_clsite);

PHPを触り始めて日が浅いもので、ループを多用して重い処理になっているのはわかっております…。
コードの書き方自体もなっていないと思いますが、タイムアウトせずに動かせなく困っておりまして、アドバイスを頂ければと思っております。

PHP・ブラウザのタイムアウト対策は、
set_time_limit(0);
ob_end_clean();
echo str_pad('',256);
flush();
sleep(1);
としており、上記で暫くは処理時間を伸ばすことができておりました。

また、phpがapachユーザー?として動く為、apachのタイムアウトに引っかかるのではと、コアサーバーのサイトに記載されていた、CGI版PHPとして動かす方法(.htaccessに記載する方法)でも試してみたのですが、結果は変わりませんでした。
しかし、本当にCGI版として動いているのか確信はありません。。

試行錯誤の上、上記のループの$iの部分を1回終了毎にブラウザに戻し、metaのRefreshで15秒開け次の処理を行わせたり、$iのループ毎に手動でPOSTにて送信し、細切れにして処理をさせているのですが、細切れにした処理だけでもタイムアウトになったりならなかったりを繰り返しております。

上記の方法では、ブラウザのタイムアウト対策をしているだけではと思いつつも、原因がどこにあるのか思い当たらない為、どう対処していいのかさえわからない状況となっております。。

単純に、apachのタイムアウトに引っかかっているのか、負荷が大きいためなんらかのサーバの制限に引っかかっているのか等、考えられる原因やその原因を一つ一つ切り捨てていけるような方法等がありましたら、ご意見お願いできればと思います。

自前のサーバの準備も進めておりますが、暫く時間がかかってしまいそうですので、現在の環境で応急処置できればと思っております。

タイムアウト時はphpなどのエラーメッセージは出ず、IEの「このページは表示できません。」というメッセージが表示されております。

乱文にて申し訳ありませんが、お知恵をお貸し頂けますと大変幸いでございます。
宜しくお願い致します。

A 回答 (6件)

execの使い方は合ってますが、どうやら制限によって難しそうですね。


そこまで制限してるならサーバー移行が良いかも知れません。

と言いつつ、一つ思いついたので書いておきます。

「実行時刻(時)の2時間前~1時間前のログのみを対象として集計する」というスクリプトを1時間に1回実行します。
2010/2/20 0:00~1:00のログは同日2時に集計
2010/2/20 1:00~2:00のログは同日3時に集計・・・
保存先のDBでそのような分割実行でも集計できるテーブルになってる必要がありますが、計算量は24分の1になるはずなのでしばらくは大丈夫だと思います。
#実際には引数でいつの分を集計するか指定できたほうが良いですが
    • good
    • 0
この回答へのお礼

execの件、確認頂きまして有難うございました。
その後いろいろと試行錯誤し、毎時間cornから処理プログラムを起動させ、一度タイムアウトまで処理を行い、1時間後はタイムアウトまでに処理されたログの集計を飛ばして、続きから処理させるようにしました。

毎時間、途中から集計処理をさせることで、全ての処理を完了するところまでいくことができました。
体感で15~30分でタイムアウトになってしまうようですので、前日の処理は日が昇る前には完了することができ、一応理想としていた処理の形とすることができました。

ただし、処理完了後も同じ処理が毎時間走ってしまいますので、集計処理用のログテーブルを作成し、前日の処理が終了したら集計処理完了ログを作成し、完了ログがあった場合は処理を中止するという仕組みにすれば、サーバーへの負荷も軽減できると思いますので、構築しようと思っております。

正直cornも正常に走っているか、深く追求しておりませんでしたので、cornを追求するきっかけを与えて頂いたyuuki0229様に感謝しております。

linuxでのサーバー構築を前倒しにして、自前サーバーにて安定した運用ができるようにしていきたいと思っております。
linuxの方もいろいろと勉強する点が多々ありますが、いろいろとお知恵をお貸し頂きまして有難うございました。

お礼日時:2010/02/20 23:01

解決策でもなく回避策でもなく、


俺なら こうするかなって言う妄想レベルの話ですので、聞き流しでお願いします。

ローカルにXAMPP入れて、ローカルからネット上にデータを取りに行って、集計したら、ネット上に戻してやる感じでやれば、多分 タイムアウトしません。
ただ、データの量的に なんか問題がある気もします。

ちなみに、俺は 最初に自分でブラウザからトリガー引いた後は、8時間以上 放置して、データをネットから自動で拾い続けさせていた事があります。
    • good
    • 0
この回答へのお礼

いろいろと策をお考え頂きまして有難うございました。
ANo,5のお礼に記載させて頂いた方法にて、処理を完了するところまで持っていくことができました。

XAMPPは一度触ったことがある程度でbm_hiro様の様に、難しい連動をさせるのには、知識不足かもしれません。。

本当にいろいろとお力をお貸し頂きまして、感謝しております。
有難うございました!

お礼日時:2010/02/20 23:05

CLI版のPHPは「/usr/bin/php5cli」で利用することが出来そうです。



しかし、CORESERVERではジョブの最大実行時間が3分間に制限されているようで、これはCGI版やモジュール版の300秒よりさらに短い設定値ですね。
CLI版のPHP自体は「max_execution_time」が0で無制限となりますが、制限により3分で強制終了するのであれば、CLI版であってもタイムアウトしてしまいますので、当方のアドバイスは無意味でした。この線は捨ててください。

参考URL:http://www.coreserver.jp/help/index.php/limitati …
    • good
    • 0
この回答へのお礼

わざわざお調べ頂きまして、有難うございました。
このような負荷制限があると、やはりサーバを移した方が賢明なのでしょうか…。

サーバー移行も含めて、いろいろと考えてみることにします。
有難うございました!

お礼日時:2010/02/19 14:30

Apache側のタイムアウト設定に依存してそうです。



Web上でやる場合、
exec("/usr/bin/php heavy_script.php > /dev/null 2>&1 &");
のようにバックグラウンドでスクリプトを実行すればひとまずApacheのタイムアウトは気にしなくてよくなります。

そして1日1回実行とのことですが手動でしょうか?
Cronから1日1回、PHPを実行すれば元々Apache関係なく処理できます。

ループのアルゴリズムに無駄があるかどうかは挙げられたコードでは判断できませんでした。
    • good
    • 0
この回答へのお礼

ご回答有難うございます。

exec関数について、使ったことがないので調べてみましたが、使い方が今ひとつ掴めません。
重い処理のスクリプト(c_batch.php)を、同じ階層に作成したexec.phpを頂いたご回答を元に下記のように記載し、exec.phpへブラウザからアクセスしたのですが、処理がされていない様です。。

↓exec.php
<?php
echo exec("/usr/bin/php ".dirname(__FILE__)."c_batch.php > /dev/null 2>&1 &");
?>

勉強不足の為、ご回答頂いた内容と全く違うことをしているかもしれません。
その際は申し訳ありません。

また、cornから…という処理方法が本来行いたい方法でした。
しかし、$iの処理回数が74回あるうち、58回終了後、処理がとまってしまってしまい、処理が中途半端で終わってしまってしまうのです。。
Apachのタイムアウトが関係ないとなると、他の原因はどのようなことが考えられますでしょうか?
できれば、cornにて午前4時頃に自動で処理を完了させてしまいたいので、重ねてのご質問になってしまい申し訳ありませんが、お力をお貸し頂ければと思います。

exec関数に関しては、理解が浅い状況ですので、引き続き理解を深めるよう勉強していきたいと思っております。

アドバイス有難うございました。

お礼日時:2010/02/19 11:52

環境が違うので参考にならないかもしれませんが、一応 そちらと同じ方法でタイムアウト防止させていて、1~2時間程度なら 問題なく動いてます。


それ以上、時間のかかることをしたことがないだけで、それ以上でも動くものと思われます。

ただ、俺の環境はXAMPPでローカルの自分のPCの中にあるテキストファイルを読み出して、解析して、DBに叩き込むだけなので、負荷は常識の範囲内だと思います。
なので、参考にはならないかもしれません。

俺も どっかから コピペしてきた奴なんですけど、そちらと同じようにして使ってます。

// タイムアウト防止処理
set_time_limit(0);// 実行時間を制限しない
ob_end_clean();// 出力をバッファリングしない(==日本語自動変換もしない)
print str_pad('',256);// IEのために256バイト空文字出力

ただ、他にも 超うろ覚えで 別のと記憶違いしてる気がしないでもないんですけど、
php.ini とか httpd.conf も いじったような気もします。

ほんと、役に立たない回答で すみません。
    • good
    • 0
この回答へのお礼

有難うございます。
おそらく環境の違いか何かでタイムアウトする時間が違うのかもしれません。

解決に向けて頑張ってみます。
有難うございました。

お礼日時:2010/02/19 11:31

おそらくCGI版と同じ場所に、CLI版のPHPが用意されています。

バッチ処理にはこれを利用すると便利です。

ロジックの見直しなどは、ローカルで行うことをお勧めします。

参考URL:http://www.php.net/manual/ja/features.commandlin …
    • good
    • 0
この回答へのお礼

有難うございます。
CLI版のPHPの導入をできるよう勉強してみます。

正直CLI版を簡単に導入して、処理を復旧できるレベルではなさそうですが…。

お礼日時:2010/02/19 11:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!