PHPである処理を行うと、約1時間かかるとします。(この時間は短縮出来ない)

そして、全く同じ時間帯にそれを50回行いたいと思います。

forやwhileを使って50回繰り返すと、最初と最後で50時間の差が出てしまいます。
cronは最小1分間隔ですが、やはり50分の差が出てしまいます。

その他、上記の事を行う為の方法・手段をご存じの方は、アドバイスいただければと思います。


※「そういう事は止めた方が良い」という根本的なご指摘の場合、明確な理由やソースをお願いします。
※処理に利用しているサーバは、Pen4 2.4GHz、RAMが1GB、CentOS4.5です。
※「ある方法」について詳しく書かないのは、その方法についての質問ではないからです。
 主にサーバの負荷対策やどの程度可能か否かを知りたいと思っています。
 サーバスペックを向上させる事で可能であれば、どの程度こなせるかの想定でも結構ですので、教えて下さい。
※質問がありましたら、コメント欄にお願いします。回答欄には回答のみお願いします。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2008/12/01 13:20:38
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:goodvn No.2

回答回数228ベストアンサー獲得回数18

ポイント100pt

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分間隔と考えないといけないこと,開始時間が予測できないので,とてつもなく遅れて開始する可能性があることです

id:k27w

まさにこの考え方です!的確に私の悩んでいる内容についての検討をしていただいていると思います。


とりあえず記載していただいたソースのようなシェルファイルを作成し、それをcronで指定時刻に実行させ、ただしく処理出来るか試してみます。


追記 上記の事を試してみました▼

要件として、mail.phpを実行後、1分経ったらメールが送信されてくる。

同時刻にメールアドレスが3通届けば同時処理として成功。

  • mail.phpのソース

sleep(60);

mail ("to@hoge","test_mail","massege","From:from@hoge");

  • cron.shのソース

#/!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通届きました。

つまり、同じ処理時間がかかるファイルにアクセスして同時刻に処理するという事が出来ているかと思います。


これで負荷テストが出来そうです。非常に参考になりました。ありがとうございました。

2008/11/30 07:19:23

その他の回答2件)

id:b-wind No.1

回答回数3344ベストアンサー獲得回数440

ポイント10pt

pcntlを使ってfork - Do You PHP はてな

fork すれば同時実行可能でしょ?

ただ、それだけ時間がかかる処理を同時実行したところで同じ時間で終わるとは思えないけど。


主にサーバの負荷対策やどの程度可能か否かを知りたいと思っています。

処理の概要(主に演算コストが高いのかIO処理が重いのか)が位は書かないと何ともいえんと思うが。

id:goodvn No.2

回答回数228ベストアンサー獲得回数18ここでベストアンサー

ポイント100pt

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分間隔と考えないといけないこと,開始時間が予測できないので,とてつもなく遅れて開始する可能性があることです

id:k27w

まさにこの考え方です!的確に私の悩んでいる内容についての検討をしていただいていると思います。


とりあえず記載していただいたソースのようなシェルファイルを作成し、それをcronで指定時刻に実行させ、ただしく処理出来るか試してみます。


追記 上記の事を試してみました▼

要件として、mail.phpを実行後、1分経ったらメールが送信されてくる。

同時刻にメールアドレスが3通届けば同時処理として成功。

  • mail.phpのソース

sleep(60);

mail ("to@hoge","test_mail","massege","From:from@hoge");

  • cron.shのソース

#/!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通届きました。

つまり、同じ処理時間がかかるファイルにアクセスして同時刻に処理するという事が出来ているかと思います。


これで負荷テストが出来そうです。非常に参考になりました。ありがとうございました。

2008/11/30 07:19:23
id:Z9M9Z No.3

回答回数343ベストアンサー獲得回数11

ポイント10pt

http://www.phppro.jp/qa/977

PHPでバッチのバックグラウンド処理がしたいということでしょうか。

  • id:ja2015
    >cronは最小1分間隔ですが、やはり50分の差が出てしまいます。

    これだと、シングルタスクの場合と数十個の並列処理の場合で処理時間が変わらないことになってしまいます。
    あまり詳しくないのですが、CentOS4.5はそんなに強力なマルチタスクを装備しているのでしょうか?

    命題の要件が明確でないですが、「時間差をなくす」ことを目的とされるなら、
    forやwhileを使って50回繰り返した後に、最後に50回分の処理結果を出力すればよいのでは?

    >サーバスペックを向上させる事で可能であれば

    とおっしゃいますが、これだと
    >ある処理を行うと、約1時間かかるとします。(この時間は短縮出来ない)
    という命題に反することになります。
    単なる思考実験でいいのなら、50台のサーバで同期処理させれば大幅に
    時間短縮できると思いますが。
  • id:k27w
    例えば、動画ファイルがあるとします。その動画が1時間のものであるとします。

    50人が同時刻にその動画ファイルにアクセスして1時間再生した場合、サーバの負荷、或いは処理能力として耐えられるのでしょうか?

    と言う質問と同等と受け取っていただければと思います。


    50人同時アクセスを実現出来ないので、forやwhileやcronについて書きましたが、これだと順番に実行される事になり、同時刻に50人が視聴するという事に値しないので、使えない。だからその他の考え方、方法を教えて下さい。

    と言った質問でもあります。


    >単なる思考実験でいいのなら、50台のサーバで同期処理させれば大幅に
    >時間短縮できると思いますが。

    おっしゃるとおり、上記の例なら動画再生ファイルを50台のサーバに置いて、50人のアクセスがあれば、それぞれのサーバに分散する。それなら負荷もそれほどかからなくて可能でしょうが、1台で利用について教えて欲しいです。無理ならなぜ無理か?どの範囲までいけるのかと言う事を教えて欲しいです。(つまり、皆様の経験上のお話が聞きたいのです)


    質問がわかりづらくて申し訳ありません。
  • id:k27w
    負荷テストの実験方法としてgoodvnさんが回答していただいた方法で出来そうです。

    質問やコメントには
    「1台のサーバでどの範囲までこなせるのか?」
    と言った質問も書いていますが、テスト方法がわかったので、
    自分で試してみます。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません