LAMP システムを調整する: 第 1 回 LAMP アーキテクチャーを理解する

LAMP システムの動作、パフォーマンスの測定法、そして基礎となるオペレーティング・システムの調整方法

LAMP (Linux®, Apache, MySQL, PHP/Perl) アーキテクチャーを使ったアプリケーションは次々と開発され、デプロイされています。しかし多くの場合、アプリケーションはサーバー管理者以外の人が作成したものであるため、サーバー管理者はアプリケーション自体をほとんどコントロールできません。この3 回シリーズの記事では、アプリケーションのパフォーマンスを向上させる、あるいは低下させる、サーバー構成上のさまざまな項目について説明します。今回の第1 回は、LAMP のアーキテクチャーと、測定を行うための方法、そして Linux のカーネルやディスク、ファイル・システムなどの基本的な調整方法について説明します。今後の記事では、Apacheと MySQL、PHP のコンポーネントの調整方法について調べます。

Sean Walberg, Senior Network Engineer, P.Eng

Photo of Sean WalbergSean Walberg は 1994年以来、学術や企業の環境で、またインターネット・サービス・プロバイダー環境で、Linux と UNIX に取り組んできています。彼は過去数年間、システム管理に関して幅広い執筆を行ってきました。



2007年 3月 31日

Linux と Apache、MySQL、そして PHP (または Perl) は、(ToDoリストからブログ、そして E コマース・サイトに至るまで)数多くの Web アプリケーションの基礎となっています。WordPress と Pligg は、ハイ・ボリュームの Web サイトを強化する一般的なソフトウェア・パッケージの単なる2 つにすぎません。このアーキテクチャーは、単純に LAMP として知られるようになりました。ほとんどすべての Linux ディストリビューションにはApache と MySQL、PHP、そして Perl が含まれているため、LAMP ソフトウェアのインストールは非常に容易です。

このようにインストールが容易なため、LAMP ソフトウェアは何も手を加えなくても動作するという印象を与えてしまいがちですが、そんなことはありません。アプリケーションに対する負荷が次第にバックエンド・サーバーの元々の設定を越えるようになり、アプリケーションのパフォーマンスが低下します。つまりLAMP のインストールは、常に監視や調整、そして評価が必要なのです。

「システムの調整」の持つ意味は、人によって異なります。この記事のシリーズでは、LAMP のコンポーネント (つまり Linux、Apache、MySQL、PHP)の調整に焦点を絞ります。アプリケーションそのものの調整は、また別の複雑さを伴います。アプリケーションとバックエンド・サーバーは相互に関係しています。サーバーの調整が不適切であれば最高のアプリケーションであっても負荷をかけると障害が発生し、また、作りの良くないアプリケーションでも速度が著しく低下する前にサーバー側で行えることは無数にあります。幸いなことに、システムを適切に調整して、監視することで、アプリケーションの中にある問題を特定することができます。

LAMP のアーキテクチャー

どのようなシステムを調整する場合であれ、最初のステップは、そのシステムがどのように動作するのかを理解することです。最も単純なレベルで、LAMPベースのアプリケーションは PHP のようなスクリプト言語で作成され、Linux ホスト上で実行している Apache Web サーバーの一部として実行されます。

PHP アプリケーションは、要求された URL、任意のフォーム・データ、取得した任意のセッション情報などによってクライアントから情報を得て、何をすべきかを判断します。必要な場合には、サーバーは(同じく Linux 上で実行している) MySQL データベースから情報を取得し、その情報を何らかの HTML (Hypertext MarkupLanguage) テンプレートと組み合わせ、そしてそれをクライアントに返します。このプロセスは、ユーザーがアプリケーションをナビゲートするごとに繰り返され、また複数の人がシステムにアクセスした場合は並行して起こります。しかしデータのフローは片方向ではありません。なぜなら、データベースは、セッション・データや統計の集合(投票など)、またユーザーが送信したコンテンツ (コメントやサイト更新) といった形式によるユーザーからの情報によって更新される場合があるからです。また動的な要素の他に、画像やJavaScript コード、CSS (Cascading Style Sheets) などの静的要素もあります。

LAMP のバリエーション

LAMP は、厳密には Linux と Apache、MySQL、そして PHP または Perl として始まりました。しかし、あまり Linuxが得意でない人にとっては、Apache と MySQL、そして PHP を Microsoft® Windows® で実行することも珍しいことではありません。さらにいつでも、Apacheの代わりに lighttpd を使うようにすることができ、それでもやはり LAMP スタイルのシステムが得られます (ただし頭文字を組み合わせても発音できる言葉にはならないかもしれません)。あるいは、別のオープンソース・データベース(PostgreSQL または SQLite)、や商用データベース ( IBM® DB2® など)、さらには商用であっても無料のエンジン(IBM DB2 Express-C など) を使うこともできます。

この記事では、本来の LAMP アーキテクチャーに焦点を絞ります。この組み合わせが、私が最も頻繁に目にするシステムであり、しかもコンポーネントはすべてオープンソースであるからです。

LAMP システムでのリクエストのフローを見れば、どこで速度低下が起こる可能性がある場所を特定できるようになります。多くの動的情報はデータベースによって提供されるため、クライアントはクエリーに対する応答の遅れに気付きます。Webサーバーはスクリプトを迅速に実行できる必要があり、また複数の同時リクエストを処理できる必要があります。最後に、基礎となるオペレーティング・システムはアプリケーションをサポートするために安定して動作している必要があります。また、ネットワークを介して他のサーバーとの間でファイルを共有するための他の設定も、ボトルネックになる可能性があります。

パフォーマンスを測定する

常にパフォーマンスを測定することによる利点は 2 つあります。第 1 に、測定することによって、傾向 (良い傾向も悪い傾向もあります) をつかむことができます。単純な例として、Webサーバーでの CPU (central processing unit) 使用率を監視することで、CPU が過負荷になっていることを知ることができます。同様に、過去に使用された合計帯域幅を監視し、それを元に将来を推定することによって、いつの時点でネットワークのアップグレードが必要かを判断することができます。こうした測定を、他の測定や観察と関連付けられればベストです。例えば、ユーザーからアプリケーションが遅いという苦情が寄せられる時にはディスクが最大容量で動作している、と判断できるかもしれません。

パフォーマンス測定の 2 番目の使い方は、調整によって状況が良くなったか悪くなったかを判断するための使い方です。そのためには、調整による変更前と変更後の測定結果を比較します。ただし、有効な比較を行うためには1 度に 1 つの項目のみを変更し、適当なメトリックで比較して、変更による効果を判断する必要があります。1 度に 1 つの項目のみを変更する理由は明白で、2つの項目を同時に変更すると、お互いが打ち消し合うことが十分に考えられるのです。それと比べれば、そのメトリックを選択した理由は、さほどはっきりしたものではありません。

観察の対象として選んだメトリックが、アプリケーションのユーザーのことを考慮したものであることが非常に重要です。もしデータベースのメモリー・フットプリントを減らすことが変更の目標である場合、さまざまなバッファーを削除することは確かに有効ですが、それによってクエリーのスピードやアプリケーションのパフォーマンスが犠牲になります。それよりも、メトリックの1 つを、アプリケーションの応答時間とすべきです。そうなると、単にデータベースのメモリー使用率以外にも、調整が必要な部分が出てくるかもしれません。

アプリケーションの応答時間は、さまざまな方法で測定することができます。おそらく最も容易な方法は、curl コマンドを使う方法でしょう (リスト 1)。

リスト 1. curl を使って Web サイトの応答時間を測定する
$ curl -o /dev/null -s -w %{time_connect}:%{time_starttransfer}:%{time_total}\
    http://www.canada.com
0.081:0.272:0.779

リスト 1 は、人気のニュース・サイトを見るために curl コマンドが使われていることを示しています。出力 (通常は HTML コードです) は -o パラメーターを使って /dev/null に送信され、-s はすべてのステータス情報をオフします。-w パラメーターは curl に対して、タイマー (表 1) などのステータス情報を書き出すように命令します。

表 1. curl が使用するタイマー
タイマー説明
time_connectサーバーへの TCP 接続を確立するまでの時間
time_starttransferリクエストが発行された後、Web サーバーがデータの最初のバイトを返すまでの時間
time_totalリクエストを完了するまでの時間

これらの 3 つのタイマーはどれも、DNS (Domain Name Service) ルックアップよりも前の、トランザクションの開始時にスタートするタイマーです。従って、リクエストが発行された後、Webサーバーがリクエストを処理してデータの返送を開始するまでに、0.272 - 0.081 = 0.191 秒かかっています。また、クライアントがサーバーからデータをダウンロードするために、0.779- 0.272 = 0.507 秒かかっています。

curl データを観察し、時間の経過による傾向を見ることによって、ユーザーにとってのサイトの応答性を的確に把握することができます。

もちろん、Web サイトは単なる 1 ページだけではありません。画像や JavaScript コード、CSS、そしてクッキーなども処理する必要があります。curl は 1 つの要素の応答時間を知るためには適切ですが、ページ全体をロードする速さを知る必要がある場合もあります。

Firefox 用の Tamper Data 拡張機能 (「参考文献」セクションにリンクがあります) は、Web ブラウザーからのすべてのリクエストをログに記録し、それぞれのリクエストも対してダウンロードに要した時間を表示します。この拡張機能を使うためには、ツール > Tamper Data を選択し、Ongoing requests ウィンドウを開きます。調べたいページをロードすると、ブラウザーからの各リクエストの状態が、その要素のロードに要した時間と共に表示されます。図1 は developerWorks のホームページをロードした場合の結果を示しています。

図 1. developerWorks のホームページをロードするために使われたリクエストの内訳
図 1. developerWorks のホームページをロードするために使われたリクエストの内訳

各行は 1 つの要素のロードを表しています。リクエストが開始された時刻、ロードに要した時間、サイズ、その結果、など、さまざまなデータが表示されています。Duration列は、その要素自体をロードするために要した時間を表しますが、Total Duration 列は、すべてのサブ要素をロードするために要した時間を表しています。図1 を見ると、メイン・ページのロード時間は 516 ミリ秒 (ms) ですが、すべてがロードされ、ページ全体が表示されるまでの時間は 5101ms でした。

Tamper Data 拡張機能の、もう 1 つの便利な点は、ページ・ロード・データの出力をグラフで表示するモードがあることです。Ongoingrequests ウィンドウの上半分のどこかで右クリックし、Graph allを選択します。図 2 は、図 1 のデータをグラフで表示したものです。

図 2. developerWorks のホームページをロードするために使用されたリクエストのグラフ表示
図 2. developerWorks のホームページをロードするために使用されたリクエストのグラフ表示

図 2 では、各リクエストに要した時間が、濃い青で、ページのロードを開始した時点を起点として表示されています。従って、どのリクエストがページ全体のロードを遅くしているかを知ることができます。

ページのロード時間やユーザー・エクスペリエンスに注目する場合でも、核となるシステム・メトリック (ディスクやメモリー、CPU、ネットワークなど)を忘れないことが重要です。この情報を捉えるためのユーティリティーは豊富にあります (最も便利なものは sarvmstatiostat でしょう)。こうしたツールに関する情報については、「参考文献」を参照してください。


基本的なシステム調整

Apache や PHP、MySQL といった、システムのコンポーネントを調整する前に、少し時間をとって、基礎となる Linux コンポーネントが適切に動作していることを確認する必要があります。当然のことですが、実行中の一連のサービスから不要なものを削除し、必要なサービスのみに限定する必要があります。そうすることはセキュリティー上の適切な習慣であるだけではなく、メモリーとCPU サイクルの両方を節約することにもつながります。

いくつかの簡単なカーネル調整

大部分の Linux ディストリビューションでは、バッファーや TCP (Transmission Control Protocol) パラメーターを控え目な値に設定して出荷されています。こうしたパラメーターを変更し、より多くのメモリーを割り当て、ネットワーク・パフォーマンスを高める必要があります。カーネル・パラメーターの設定は、proc インターフェースを使って /proc に値を読み書きすることで行います。幸い、sysctl プログラムを使えば、こうしたことを比較的容易に行うことができます (sysctl は /etc/sysctl.conf から値を読み取り、必要に応じて /proc にデータを設定します)。リスト 2 は、インターネット・サーバーとして使えるようにするための、より積極的なネットワーク設定を示しています。

リスト 2. より積極的なネットワーク設定を行う /etc/sysctl.conf
# Use TCP syncookies when needed
net.ipv4.tcp_syncookies = 1
# Enable TCP window scaling
net.ipv4.tcp_window_scaling: = 1
# Increase TCP max buffer size
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# Increase Linux autotuning TCP buffer limits
net.ipv4.tcp_rmem = 4096 87380 16777216 
net.ipv4.tcp_wmem = 4096 65536 16777216
# Increase number of ports available
net.ipv4.ip_local_port_range = 1024 65000

このファイルを、既に /etc/sysctl.conf の中にあるものに追加します。最初の設定は TCP SYN クッキーを有効にします。クライアントから、SYN ビットがセットされたパケットで新しいTCP 接続を受信すると、サーバーは half-open 接続に対してエントリーを作成し、そして SYN-ACK パケットで応答します。通常のオペレーションでは、リモート・クライアントはACK パケットで応答し、このパケットによって、half-open 接続が完全な接続になります。SYN フラッドと呼ばれる攻撃は、クライアントがACK パケットを返さないようにすることで、サーバーが新たに受信した接続を処理するリソースが不足した状態になるようにします。SYN クッキー機能はこの状態を認識し、キューの中にスペースを確保するスマートな方法を開始します(完全な詳細については「参考文献」を参照してください)。ほとんどのシステムでは、デフォルトでこれを有効にしていますが、念のため、この構成を確認する必要があります。

TCP ウィンドウのスケーリングを有効にすると、クライアントはより高速にデータをダウンロードすることができます。TCP は、リモート側からの確認応答がなくても、デフォルトで64 キロバイト (KB) (遅延の大きなピアと通信する場合には満杯になる可能性があります) までのパケットを送信することができます。ウィンドウ・スケーリングを行う場合は、このウィンドウのサイズを拡大するために、ヘッダーの中でいくつか追加のビットを使うことができます。

次の 4 つの構成項目は、TCP の送受信バッファーを増加させます。これによってアプリケーションはデータを素早くバッファーに移動させ、別のリクエストを処理できるようになります。また、サーバーがビジーになった場合のリモート・クライアントのデータ送信能力も改善されます。

最後の構成項目は、使用可能なローカル・ポートの数を増加させます。これによって、同時に処理される最大接続数も大きくなります。

これらの設定は、次回に起動したとき、あるいは sysctl -p /etc/sysctl.conf を実行したときに有効になります。

最大パフォーマンスが得られるようにディスクを構成する

ディスクは LAMP アーキテクチャーで非常に重要な役割を果たします。静的ファイル、テンプレート、そしてコードは、データベースを構成するデータ表や索引と同様に、ディスクから提供されます。ここから先の、調整(特にデータベースに関係する調整) についての説明の大部分は、ディスク・アクセスを避ける方法に焦点を絞ります。ディスク・アクセスを避けるのは、それによる遅延が比較的大きいためです。したがって、ディスク・ハードウェアを最適化するために時間を使うことは、意味のあることです。

まず第 1 に、ファイル・システムに対して atime ログが無効になっていることを確認します。atime は最後にそのファイルにアクセスした時刻であり、あるファイルがアクセスされるごとに、ベースにあるファイル・システムはそのタイムスタンプを記録する必要があります。システム管理者がatime を使うことは稀なため、これを無効にすることで、ディスクにアクセスする時間を少し減らすことができます。そのためには、/etc/fstab の4 番目の列に noatime オプションを追加します。リスト 3 はこの構成例を示しています。

リスト 3. noatime を有効にする fstab の例
/dev/VolGroup00/LogVol00 /                      ext3    defaults,noatime        1 1
LABEL=/boot             /boot                   ext3    defaults,noatime        1 2
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
sysfs                   /sys                    sysfs   defaults        0 0
LABEL=SWAP-hdb2         swap                    swap    defaults        0 0
LABEL=SWAP-hda3         swap                    swap    defaults        0 0

リスト 3 では ext3 ファイル・システムのみが変更されていますが、これは noatime がディスク上に存在するファイル・システムのみに対して有効なためです。この変更を有効にするためにリブートの必要はなく、各ファイル・システムを再マウントすればよいだけです。例えばルート・ファイル・システムを再マウントするためには、mount / -o remount を実行します。

ディスク・ハードウェアはさまざまな組み合わせが可能であり、Linux はそうしたディスク群に対して、必ずしも確実に最適なアクセス方法を検出できるわけではありません。IDE(integrated development environment: 統合開発環境) ディスクにアクセスするための方法を取得し、設定するためには、hdparm コマンドが使われます。hdparm -t /path/to/device と入力すると、スピード・テストが実行されるため、これをベンチマークとして使用することができます。最も信頼性の高い結果を得るためには、このコマンドを実行する際にはシステムがアイドル状態にある必要があります。リスト4 は、hda 上で実行したスピード・テストを示しています。

リスト 4. /dev/hda 上で実行したスピード・テスト
# hdparm -t /dev/hda

/dev/hda:
 Timing buffered disk reads:  182 MB in  3.02 seconds =  60.31 MB/sec

このテストからわかるように、ディスクは、毎秒約 60 MBでデータを読み取っています。

ディスク調整のオプションに入る前に、注意すべき点をあげておきます。不適切な設定を行うと、ファイル・システムを破損する恐れがあります。そのオプションがハードウェアに対応していないという警告が出ることもあれば、出ないこともあります。こうした理由から、システムを稼働状態にする前に、設定を十分にテストする必要があります。この意味からも、サーバー全体に標準的なハードウェアを使用した方が得策です。

表 2 は、一般的なオプションのいくつかを示しています。

表 2. hdparm の一般的なオプション
オプション説明
-viドライブを照会し、そのドライブがどの設定をサポートし、どの設定を使用しているかを判断します。
-c(E) IDE 32 ビット I/O サポートを照会、あるいは有効にします。hdparm -c 1 /dev/hda は、このサポートを有効にします。
-m割り込みモードごとのセクター数を照会、あるいは設定します。設定がゼロよりも大きい場合、割り込みごとに、そのセクター数まで転送することができます。
-d 1 -XDMA (direct memory access) 転送を有効にし、IDE 転送モードを設定します。hdparm の man ページには、-x の後に来る数字の詳細な説明があります。これを行う必要があるのは、最高速モードが使われていないことが -vi からわかる場合のみです。

残念ながら、ファイバー・チャネル・システムと SCSI (Small Computer Systems Interface) システムの場合は、調整は特定のドライバーに依存します。

この中で便利と思える設定があれば、それを起動スクリプト (例えば rc.local など) に追加する必要があります。

NFS の調整

NFS (network file system) はネットワークにまたがってディスク・ボリュームを共有する方法です。NFS は、確実にすべてのホストが同じデータのコピーを持ち、また変更が全ノードに渡って反映されるようにするために使用できます。ただしNFS は、デフォルトではハイ・ボリューム用には構成されていません。

各クライアントは、リモートのファイル・システムを rsize=32768,wsize=32768,intr,noatime という設定でマウントする必要があります。これによって下記を保証することができます。

  • 大きな読み書きブロック・サイズが使われる (指定される大きさ (この場合は 32KB) まで)
  • ハングアップした場合には NFS 動作が中断される
  • atime が常時更新されることがない

これらの設定は、リスト 3 に示したように /etc/fstab の中に含めることができます。オートマウンターを使っている場合には、これらは適切な /etc/auto.* ファイルの中に入ります。

サーバー側に関しては、すべてのクライアントを処理するために十分な NFS カーネル・スレッドがあることを確認することが重要です。デフォルトでは、1つのスレッドしか起動しません (ただし Red Hat と Fedora のシステムは 8 つのスレッドから始まります)。負荷の重い NFSサーバーの場合には、この数字をもっと大きく、例えば 32 や 64 のようにする必要があります。また、ブロックされているものがないかどうか、nfsstat -rc コマンドを使ってクライアントを調べることができます (nfsstat -rc コマンドはクライアントの RPC (Remote ProcedureCall) 統計を示します)。リスト 5 は、Web サーバーに対するクライアント統計を示しています。

リスト 5. NFS クライアントの RPC 統計を示す
# nfsstat -rc
Client rpc stats:
calls      retrans    authrefrsh
1465903813   0          0

2 番目の列、retrans はゼロです。これは、最後にリブートされてから、再送信が必要なかったことを示しています。この数字が増加しているようであれば、さらに NFS カーネル・スレッドを追加することを検討する必要があります。そのためには、必要なスレッド数をrpc.nfsd に渡します (例えば 128 本のスレッドを開始するには、rpc.nfsd 128 のようにします)。この変更はいつでも行うことができます。スレッドは、必要に応じて開始することも、廃棄することもできます。これも、起動スクリプトの中(できれば、そのシステムで NFS を起動するスクリプトの中) に入れます。

NFS に関する最後の注意として、NFSv2 は v3 や v4 よりもパフォーマンスが大幅に低いため、できれば避けた方が無難です。これは最近のLinux ディストリビューションでは問題ありませんが、サーバーで nfsstat を実行した結果をチェックして、NFSv2 が呼び出されていないかどうかを調べる必要があります。


次回は

この記事は、LAMP の基本と、LAMP インストールのための単純な Linux 調整について説明しました。NFS カーネル・スレッドを除けば、この記事で説明したさまざまなパラメーターは、設定した後は無視することができます。このシリーズの今後の2 回の記事では、Apacheと MySQL、そして PHP の調整に焦点を絞ります。これらの調整は Linux の調整とはかなり異なります。これは、トラフィック・ボリュームの増加や読み取りと書き込みの分布の変化、またアプリケーションの進化に合わせて、常にパラメーターを再検討する必要があるためです。

参考文献

学ぶために

製品や技術を入手するために

  • Firefox 用のTamper Data拡張機能を利用すると、HTTP ヘッダーを即時処理で表示し、変更することができ、またページ要素のロード動作をグラフ化することができます。
  • developerWorks から直接ダウンロードできる IBM trial softwareを使って皆さんの次期開発プロジェクトを構築してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source, Web development
ArticleID=245809
ArticleTitle=LAMP システムを調整する: 第 1 回 LAMP アーキテクチャーを理解する
publish-date=03312007