2011年12月09日

php のプロセス数を絞ろう

はてなブックマークに登録

KLab Advent Calendar 2011 「DSAS for Social を支える技術」の7日目です。 @methane の新シリーズは Apache+php のチューニングです。

今日のお題は、タイトルのとおり、phpのプロセス数(=並列数)を減らすことです。 これはチューニンガソンでも人気のチューニングだったのですが、 今日はそのメリットをまとめます。

ロードアベレージが下がる

プロセス数をコア数+α程度に抑えると、ロードアベレージがコア数の数倍〜 数十倍になることがなくなります。

例えばロードアベレージがコア数の100倍になると、1リクエストの処理に かかる時間は100倍以上に増え、せっかく処理したのにクライアント側が タイムアウトしていて完全に無駄骨になったり、最悪では再リクエストが来て さらに負荷が上がる負のスパイラルに陥る可能性があります。

たくさん一気に処理しようとしてアップアップするよりも、 能力の範囲内の処理だけを全力で実行し、次のリクエストは今のリクエストが 終わってから実行するほうが健全です。

並列数を絞ると、処理待ちのリクエストが増えて行きますが、このあたりについては 次回に回します。

コンテキストスイッチが減る

実行可能なプロセス数が多いと、IO待ち以外でもコンテキストスイッチが 発生するようになります。コンテキストスイッチが発生すると、OSの処理も 発生しますし、TLBなどのキャッシュが無効になったりするので、パフォーマンスに 影響します。

通常のマシンではコンテキストスイッチの負荷はphpの処理自体の負荷に比べて 圧倒的に軽いのですが、仮想マシンを使うと実マシンにくらべてオーバーヘッドが 増える傾向があります。 チューニンガソンで並列数を絞る設定が定番なのも、仮想環境でのチューニング だからです。

MySQLの接続数やロック時間、その他のリソースの消費が減る

MySQL への接続を永続化している場合、並列数がそのままMySQLの接続数に なります。

リクエスト毎にMySQLに接続する場合も、phpが最初のほうでMySQLに接続し 最後のほうで切断する場合は、平均処理時間[sec]×秒間リクエスト が MySQL への平均接続数になります。例えば応答速度が 0.1sec で秒間リクエスト数が 4000なら、平均接続数は400になります。

同じことが、トランザクションやロックなどについても言えます。 OSのスケジューラは、phpがMySQLに接続しているかどうかや、ロックを持っているか どうかなどを考慮せずにスケジューリングするので、トランザクション中のphpの 実行を止めて新規リクエストの処理をするプロセスを実行してしまうことが あるからです。

MySQL の接続数や負荷の上限を抑えられる

接続数の上限は並列数になるので、MySQLの max_connections を並列数 (1台あたりの並列数xサーバー台数)以下に設定することで、 接続数をオーバーしなくなります。

MySQLの最大接続数を超えた時、MySQL は Too Many Connections というエラーを 返して接続をすぐに切断するのですが、このエラーが起きたときに php で どう処理していいのかは難しい問題です。バッチなどでコンマ数秒程度重いだけなら リトライすれば良いのですが、MySQLが過負荷になっているときにリトライすると 問題を拡大します。

また、過負荷でMySQLに接続できないときにユーザーにエラーページを返すと、 そのユーザーがリロードして、さらに負荷が増えるという悪循環になることも あります。

並列数を絞った場合は、 MySQL の応答速度が低下した場合はどんどん MySQLに接続するのではなく新規リクエストの処理を待たせることになります。 バッチなどによる短時間の問題の場合は一瞬レスポンスタイムが低下する だけで一切エラーを発生させずにちゃんと捌けます。 MySQLが過負荷に陥った場合も、どんどんMySQLに負荷をかけたあげく タイムアウトで全部のリクエストをエラーにするのではなく、 新規リクエストを php でも MySQL でも処理せずにエラーにすることで、 処理できる範囲のリクエストにはきちんとレスポンスを返すことができます。

他の性能の上限が決まっているバックエンドのリソースについても同じことが言え、 全部のリクエストを処理しようとして過負荷になって全部タイムアウトするのではなく、 性能限界まではきちんと処理を行いレスポンスを返しつつ、上限を超える部分は 一切負荷をかけないで最初からエラーにできます。

まとめ

並列数削減は、安いレンタルサーバーでメモリ消費を抑えるための設定として 紹介されることが多いですが、大量にメモリを積んだ高性能なWebサーバーでも 大きな利点があります。

次回は、phpの並列数を超えたアクセスをどう待たせ、待ち時間が増えたときに どう処理せずにエラーを返すかの解説をしながら、実際の Apache の設定を 紹介します。


@methane
klab_gijutsu2 at 23:01│Comments(0)TrackBack(0)apache | php

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント