現在、レンタルサーバ(コアサーバー)上で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の「このページは表示できません。」というメッセージが表示されております。
乱文にて申し訳ありませんが、お知恵をお貸し頂けますと大変幸いでございます。
宜しくお願い致します。
No.5ベストアンサー
- 回答日時:
execの使い方は合ってますが、どうやら制限によって難しそうですね。
そこまで制限してるならサーバー移行が良いかも知れません。
と言いつつ、一つ思いついたので書いておきます。
「実行時刻(時)の2時間前~1時間前のログのみを対象として集計する」というスクリプトを1時間に1回実行します。
2010/2/20 0:00~1:00のログは同日2時に集計
2010/2/20 1:00~2:00のログは同日3時に集計・・・
保存先のDBでそのような分割実行でも集計できるテーブルになってる必要がありますが、計算量は24分の1になるはずなのでしばらくは大丈夫だと思います。
#実際には引数でいつの分を集計するか指定できたほうが良いですが
execの件、確認頂きまして有難うございました。
その後いろいろと試行錯誤し、毎時間cornから処理プログラムを起動させ、一度タイムアウトまで処理を行い、1時間後はタイムアウトまでに処理されたログの集計を飛ばして、続きから処理させるようにしました。
毎時間、途中から集計処理をさせることで、全ての処理を完了するところまでいくことができました。
体感で15~30分でタイムアウトになってしまうようですので、前日の処理は日が昇る前には完了することができ、一応理想としていた処理の形とすることができました。
ただし、処理完了後も同じ処理が毎時間走ってしまいますので、集計処理用のログテーブルを作成し、前日の処理が終了したら集計処理完了ログを作成し、完了ログがあった場合は処理を中止するという仕組みにすれば、サーバーへの負荷も軽減できると思いますので、構築しようと思っております。
正直cornも正常に走っているか、深く追求しておりませんでしたので、cornを追求するきっかけを与えて頂いたyuuki0229様に感謝しております。
linuxでのサーバー構築を前倒しにして、自前サーバーにて安定した運用ができるようにしていきたいと思っております。
linuxの方もいろいろと勉強する点が多々ありますが、いろいろとお知恵をお貸し頂きまして有難うございました。
No.6
- 回答日時:
解決策でもなく回避策でもなく、
俺なら こうするかなって言う妄想レベルの話ですので、聞き流しでお願いします。
ローカルにXAMPP入れて、ローカルからネット上にデータを取りに行って、集計したら、ネット上に戻してやる感じでやれば、多分 タイムアウトしません。
ただ、データの量的に なんか問題がある気もします。
ちなみに、俺は 最初に自分でブラウザからトリガー引いた後は、8時間以上 放置して、データをネットから自動で拾い続けさせていた事があります。
いろいろと策をお考え頂きまして有難うございました。
ANo,5のお礼に記載させて頂いた方法にて、処理を完了するところまで持っていくことができました。
XAMPPは一度触ったことがある程度でbm_hiro様の様に、難しい連動をさせるのには、知識不足かもしれません。。
本当にいろいろとお力をお貸し頂きまして、感謝しております。
有難うございました!
No.4
- 回答日時:
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 …
わざわざお調べ頂きまして、有難うございました。
このような負荷制限があると、やはりサーバを移した方が賢明なのでしょうか…。
サーバー移行も含めて、いろいろと考えてみることにします。
有難うございました!
No.3
- 回答日時:
Apache側のタイムアウト設定に依存してそうです。
Web上でやる場合、
exec("/usr/bin/php heavy_script.php > /dev/null 2>&1 &");
のようにバックグラウンドでスクリプトを実行すればひとまずApacheのタイムアウトは気にしなくてよくなります。
そして1日1回実行とのことですが手動でしょうか?
Cronから1日1回、PHPを実行すれば元々Apache関係なく処理できます。
ループのアルゴリズムに無駄があるかどうかは挙げられたコードでは判断できませんでした。
ご回答有難うございます。
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関数に関しては、理解が浅い状況ですので、引き続き理解を深めるよう勉強していきたいと思っております。
アドバイス有難うございました。
No.2
- 回答日時:
環境が違うので参考にならないかもしれませんが、一応 そちらと同じ方法でタイムアウト防止させていて、1~2時間程度なら 問題なく動いてます。
それ以上、時間のかかることをしたことがないだけで、それ以上でも動くものと思われます。
ただ、俺の環境はXAMPPでローカルの自分のPCの中にあるテキストファイルを読み出して、解析して、DBに叩き込むだけなので、負荷は常識の範囲内だと思います。
なので、参考にはならないかもしれません。
俺も どっかから コピペしてきた奴なんですけど、そちらと同じようにして使ってます。
// タイムアウト防止処理
set_time_limit(0);// 実行時間を制限しない
ob_end_clean();// 出力をバッファリングしない(==日本語自動変換もしない)
print str_pad('',256);// IEのために256バイト空文字出力
ただ、他にも 超うろ覚えで 別のと記憶違いしてる気がしないでもないんですけど、
php.ini とか httpd.conf も いじったような気もします。
ほんと、役に立たない回答で すみません。
有難うございます。
おそらく環境の違いか何かでタイムアウトする時間が違うのかもしれません。
解決に向けて頑張ってみます。
有難うございました。
No.1
- 回答日時:
おそらくCGI版と同じ場所に、CLI版のPHPが用意されています。
バッチ処理にはこれを利用すると便利です。ロジックの見直しなどは、ローカルで行うことをお勧めします。
参考URL:http://www.php.net/manual/ja/features.commandlin …
有難うございます。
CLI版のPHPの導入をできるよう勉強してみます。
正直CLI版を簡単に導入して、処理を復旧できるレベルではなさそうですが…。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
コマンドライン実行からのDB接...
-
PHPでサーバーにインストールさ...
-
サーバーモジュールとCGIプロセ...
-
JSのWINOW.CONFI...
-
mysql_queryの処理速度が遅い
-
xmlの宣言文をPHPで出力するには
-
フォントの色を変えるには?
-
配列とオブジェクトの違い
-
PHP session_destroyとsession...
-
mail関数を使用しても送られない。
-
会員サイトに自動ログインして...
-
iframeからのアクセスか、ブラ...
-
iphoneで虫眼鏡の作り方
-
mb_send_mail でスパム扱いとなる
-
リンク先を隠す方法はないでし...
-
2つの画像ファイルが異なるファ...
-
URLが.PHPってどういう...
-
さくらサーバーにて、phpからメ...
-
「クラス関数」「メンバ関数」...
-
PHPのif文でその処理を途中で抜...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ヒアドキュメントの中で演算子...
-
PHPからバッチファイルの実行
-
mysql複数レコードをまとめて削...
-
PHPでサーバーにインストールさ...
-
Switch文における、returnとbre...
-
PHPでコマンドプロンプトを実行...
-
phpからエクセルのマクロを実行...
-
【PHP】命令は記述順に処理...
-
PHPで、C#のプログラムを実行す...
-
別サーバのプログラムを起動
-
JSのWINOW.CONFI...
-
htmlでsubmitで指定したAction...
-
require_onceが動いていない
-
systemをrootで実行したい
-
PHPで外部プログラムのバックグ...
-
PHPからlhaコマンドを使いたい
-
phpスクリプトのみで定期実行
-
PHPでUNIXシステムコマンド...
-
PHPからexecを使ってGnuPGを実...
-
PHPスクリプトからサービスの再...
おすすめ情報