こんにちはエンジニアのオータケです!
今回はWebアプリケーション開発で起きる問題「タイムアウト」について解説をしていきます!
皆さんは普段ネットサーフィン、Webブラウジング中にアクセスしたサイトが重く待たされた上に「タイムアウトしました」というメッセージを表示されて憤怒したことはありませんか?
今回は
・タイムアウトがなぜ起こるのか
・発生しづらくするための方法
という疑問・対策から
・意図的にタイムアウトを起こすにはどうするのか
を解説していきたいと思います。
※本記事は開発者向けの内容であるため普段Webブラウジングしている人やネットサーフィンをしている人向けの記事ではありません。
タイムアウトとは?
みなさんがWebページを見ている際に普段はすぐに表示されるのに突然Webサイトが重くなっってタイムアウトと表示されたり、待たされた挙げ句、エラーのような文言が表示されて困ったなんてことありませんか?
タイムアウトとは何らかの原因で一定時間内に処理が終わらなかった場合に処理を中止することを言います。
なぜこのような仕組みがあるかというと、何らかの原因で処理が終わらず続行し続けることでサーバー自体に負荷をかけるだけでなく、アプリケーションの制御自体ができなくなる可能性もあるためです。
こういった強制的に処理を中止する仕組みがPHPにも備わっています。
ここで「何らかの原因」と書きました。
いくつか原因があるのですが「無限ループ」によって処理が続行不能に陥ったり、膨大なデータを扱う処理で思ったよりも処理に時間がかかり、延々と処理をしているなどの原因があります。
次の章ではこのタイムアウトを起こさないようにするためにはどうすべきかを解説していきます。
開発者としてタイムアウトを起こさないようにしたい
タイムアウトを可能な限り起こさないようにするにはいくつかの方法がありますが、PHPでタイムアウト時間を設定することで実現可能です。
その種類はphp.iniを編集する方法と、プログラム中で関数を呼び出す方法があるのでその2つを見ていきましょう。
php.iniで行う方法
まずphp.iniというPHPを動かす際に使われる設定ファイルの一部を変更してタイムアウト時間を設定方法について見てみましょう。
WindowsやMac、Linuxによってphp.iniファイルの存在場所が違います。
そのため一概にどことは言えませんが各環境でファイルの検索を行い発見すると良いでしょう。
見つけたらphp.iniを開きます。
環境やPHPのバージョンによってこのphp.iniの内容が少し違うのですが筆者の環境では383行目付近に以下の記述があります。
php.ini
; Maximum execution time of each script, in seconds ; http://php.net/max-execution-time ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 30
この中でmax_execution_timeという項目があるかと思います。
ここには30を代入していますがこれは30秒で実行が終了しなければタイムアウトとするという設定です。
つまり、この値を変更すればタイムアウトが発生する時間を変更することができます。
ただし注意しないといけない点としてこの時間を伸ばせば伸ばすほど、サーバーに負荷がかかるという点です。
Webサイトは同時に何人も訪問してくるため人が多ければ多いほど負荷のかかる処理をサーバーに行わせることになります。
そのためサーバーは負担がかかり、サーバーの処理能力の限界を超えるとサーバーが機能停止状態となることがあります。
どの程度時間を伸ばすかはサーバーの性能やWebアプリケーションの処理の重さ、アクセス負荷がどのくらいあるかなどを考慮して設定しましょう。
ちなみにこの30という値を0にすると処理が終わるまで待つことができます。
ただ、0にするということは処理が終わり続けるまで続行することになるため前述した負荷を考慮する必要があるでしょう。
次の項では関数でタイムアウト時間を変更したいと思います。
関数で行う方法
先程はphp.iniを使ってタイムアウトの時間を変更しました。
今度はプログラム中で関数を呼び出してタイムアウト時間を変更する方法について解説します。
<?php set_time_limit(15); // 省略 ?>
こういう形で設定をするだけでphp.iniでやったことと同じ効果を得られます。
今回の場合は15を引数で渡しているので15秒は通常通り処理を行いますがこの時間を超えたらタイムアウトとなります。
この関数を使う方法については一点問題があり、PHP自体がセーフモードで実行されている場合にはこの関数は効果がないというこことです。
もし、セーフモードがオンになっている場合はphp.iniの方法で設定するようにしてください。
開発時に意図的にタイムアウトを起こしたい
最後にプログラム上で意図的にタイムアウトを引き起こしたい場合どうすればよいかを解説します。
実行時のテストなどが目的で意図的にタイムアウトを引き起こしたい場合はsleepを使うことで実現することができます。
コードはとても簡単なので見てみましょう。
<?php set_time_limit(1); sleep(5); ?>
このコードでは実行時間を1秒にしており、2秒以上処理にかかる場合はタイムアウトになります。
sleep関数を使って5秒待ちます。
すると、2秒以上処理がかかる場合はタイムアウトになるためタイムアウトしてしまうというプログラムです。
他にはwhileやfor文を使って無限ループを作る方法もありますがここでは解説しません。
まとめ
いかがでしょうか?
普段、Webサイトを構築しておわり!となりそうですが実際にはユーザーが使うことも考えてタイムアウトしないようなサイトづくりを行わなければなりません。
実行に時間のかかる重い処理があれば改善する、頻繁にタイムアウトが起きないような適切な時間設定など考えてサイトを作っていきましょう!