そして、全く同じ時間帯にそれを50回行いたいと思います。
forやwhileを使って50回繰り返すと、最初と最後で50時間の差が出てしまいます。
cronは最小1分間隔ですが、やはり50分の差が出てしまいます。
その他、上記の事を行う為の方法・手段をご存じの方は、アドバイスいただければと思います。
※「そういう事は止めた方が良い」という根本的なご指摘の場合、明確な理由やソースをお願いします。
※処理に利用しているサーバは、Pen4 2.4GHz、RAMが1GB、CentOS4.5です。
※「ある方法」について詳しく書かないのは、その方法についての質問ではないからです。
主にサーバの負荷対策やどの程度可能か否かを知りたいと思っています。
サーバスペックを向上させる事で可能であれば、どの程度こなせるかの想定でも結構ですので、教えて下さい。
※質問がありましたら、コメント欄にお願いします。回答欄には回答のみお願いします。
1時間掛かる処理が50回,並列しないで行うとすると,確かに50時間です
1分置きに起動した場合,50個目は最初のプロセスとは50分の差はありますが,起動時に,最初のプロセスはまだ動いています
つまり,50分後で50個のプロセスが並列して動いている状態になります
50個並列しても,処理時間が1時間で済むのであれば,サーバの負荷的には問題ないわけですから,1分置きに起動せず,一気に50個のプロセスを始めてしまえばいい,という結果になります
もし逆に,プロセスがリソースを100%近く使ってしまい,2個並列したらそれぞれ2時間掛かるようになるのだとしたら,並列化は開始時間と終了時間を近づけることはできるものの,すべての処理を終えるのに50時間掛かることに変わりはありません
これはどちらか分からないので,前者(50個のプロセスが並列可能である)という前提であれば,各プロセスをバックグラウンドで実行すれば,同時に実行を開始できます
バックグラウンドでの起動とは,
$ /usr/local/bin/php -f ./program.php &
という形で可能です.これで起動したプロセスは,シェルのバックグラウンドへ行ってしまいますので,即座に次のプロセスを立ち上げられます.ここでは,例えば,-p という引数で各プロセスを区別すると仮定します
$ /usr/local/bin/php -f ./program.php -p 1 & $ /usr/local/bin/php -f ./program.php -p 2 & $ /usr/local/bin/php -f ./program.php -p 3 & : $ /usr/local/bin/php -f ./program.php -p 50 &
これで一瞬でプロセスを開始できます
sh には for というコマンドがあるので,これを使えば,わざわざ全てのプロセスについてコマンドを打つ必要すらありません
この方法の問題は,サーバの負荷を考えずにプロセスを立ち上げてしまうことです.ロードアベレージがとてつもないことになり,コマンドすら受け付けなくなる恐れがあります(Linux はこういう高負荷な運用がニガテです.FreeBSD などは比較的大丈夫です)
at コマンドのサブセットに,batch コマンドがあります.このコマンドは,指定した時間にコマンドを実行する at コマンドの機能に加え,負荷が指定したロードアベレージ以下の場合に実行する,という動きをします
つまり,もし負荷が低ければプロセスが開始され,負荷が高い場合は,負荷が下がるのを待ちます
このコマンドを使うデメリットは,開始時間の精度が低く,だいたい 5分間隔と考えないといけないこと,開始時間が予測できないので,とてつもなく遅れて開始する可能性があることです
pcntlを使ってfork - Do You PHP はてな
fork すれば同時実行可能でしょ?
ただ、それだけ時間がかかる処理を同時実行したところで同じ時間で終わるとは思えないけど。
主にサーバの負荷対策やどの程度可能か否かを知りたいと思っています。
処理の概要(主に演算コストが高いのかIO処理が重いのか)が位は書かないと何ともいえんと思うが。
1時間掛かる処理が50回,並列しないで行うとすると,確かに50時間です
1分置きに起動した場合,50個目は最初のプロセスとは50分の差はありますが,起動時に,最初のプロセスはまだ動いています
つまり,50分後で50個のプロセスが並列して動いている状態になります
50個並列しても,処理時間が1時間で済むのであれば,サーバの負荷的には問題ないわけですから,1分置きに起動せず,一気に50個のプロセスを始めてしまえばいい,という結果になります
もし逆に,プロセスがリソースを100%近く使ってしまい,2個並列したらそれぞれ2時間掛かるようになるのだとしたら,並列化は開始時間と終了時間を近づけることはできるものの,すべての処理を終えるのに50時間掛かることに変わりはありません
これはどちらか分からないので,前者(50個のプロセスが並列可能である)という前提であれば,各プロセスをバックグラウンドで実行すれば,同時に実行を開始できます
バックグラウンドでの起動とは,
$ /usr/local/bin/php -f ./program.php &
という形で可能です.これで起動したプロセスは,シェルのバックグラウンドへ行ってしまいますので,即座に次のプロセスを立ち上げられます.ここでは,例えば,-p という引数で各プロセスを区別すると仮定します
$ /usr/local/bin/php -f ./program.php -p 1 & $ /usr/local/bin/php -f ./program.php -p 2 & $ /usr/local/bin/php -f ./program.php -p 3 & : $ /usr/local/bin/php -f ./program.php -p 50 &
これで一瞬でプロセスを開始できます
sh には for というコマンドがあるので,これを使えば,わざわざ全てのプロセスについてコマンドを打つ必要すらありません
この方法の問題は,サーバの負荷を考えずにプロセスを立ち上げてしまうことです.ロードアベレージがとてつもないことになり,コマンドすら受け付けなくなる恐れがあります(Linux はこういう高負荷な運用がニガテです.FreeBSD などは比較的大丈夫です)
at コマンドのサブセットに,batch コマンドがあります.このコマンドは,指定した時間にコマンドを実行する at コマンドの機能に加え,負荷が指定したロードアベレージ以下の場合に実行する,という動きをします
つまり,もし負荷が低ければプロセスが開始され,負荷が高い場合は,負荷が下がるのを待ちます
このコマンドを使うデメリットは,開始時間の精度が低く,だいたい 5分間隔と考えないといけないこと,開始時間が予測できないので,とてつもなく遅れて開始する可能性があることです
まさにこの考え方です!的確に私の悩んでいる内容についての検討をしていただいていると思います。
とりあえず記載していただいたソースのようなシェルファイルを作成し、それをcronで指定時刻に実行させ、ただしく処理出来るか試してみます。
要件として、mail.phpを実行後、1分経ったらメールが送信されてくる。
同時刻にメールアドレスが3通届けば同時処理として成功。
sleep(60); mail ("to@hoge","test_mail","massege","From:from@hoge"); |
#/!bin/sh php /home/test/public_html/mail.php -p 1 & php /home/test/public_html/mail.php -p 2 & php /home/test/public_html/mail.php -p 3 & |
これをcronで7:00に実行したところ、約1分後の7:01:01にメールが3通届きました。
つまり、同じ処理時間がかかるファイルにアクセスして同時刻に処理するという事が出来ているかと思います。
これで負荷テストが出来そうです。非常に参考になりました。ありがとうございました。
まさにこの考え方です!的確に私の悩んでいる内容についての検討をしていただいていると思います。
とりあえず記載していただいたソースのようなシェルファイルを作成し、それをcronで指定時刻に実行させ、ただしく処理出来るか試してみます。
追記 上記の事を試してみました▼
要件として、mail.phpを実行後、1分経ったらメールが送信されてくる。
同時刻にメールアドレスが3通届けば同時処理として成功。
sleep(60);
mail ("to@hoge","test_mail","massege","From:from@hoge");
#/!bin/sh
php /home/test/public_html/mail.php -p 1 &
php /home/test/public_html/mail.php -p 2 &
php /home/test/public_html/mail.php -p 3 &
これをcronで7:00に実行したところ、約1分後の7:01:01にメールが3通届きました。
つまり、同じ処理時間がかかるファイルにアクセスして同時刻に処理するという事が出来ているかと思います。
これで負荷テストが出来そうです。非常に参考になりました。ありがとうございました。