本記事は、前の記事
「gethostbyaddr()って外部と通信するんだね」
と同時進行していた話です。よければ一緒にご覧ください。
#【 概要 】
PHPのあるシステムで、なぜかブラウザ表示が
重くなる現象が起きていました。
まず対象のページについて、テスト環境で調べました。
すると apache のログ( /var/log/httpd/ )が妙なのです。
ページに1回だけアクセスしたはずなのに、
ログ上は2回アクセスしているのです。
はぁっ? と思い、その2回目のログをよく見ると、
リモートIP(通信元)が、サーバIPと同じでした。
つまり、自サーバから自サーバに通信していたのです。
その後いろいろ調べたところ、
getimagesize() が原因だと突き止めました。
(画像の大きさを取得する関数です。)
#【 原因 】
最初に言っておきますが、
getimagesize() に罪はありません。
コールの仕方に問題があったのです。
まず getimagesize() の引数 filename は、
主に2種類の書き方ができます。
[ローカルファイル形式]
/var/www/image.gif[URL形式]
http: //xxxx.yyy/image.gif
ここで、画像が自サーバ内にある場合は、
どちらの書き方でもコール可能です。
ただし http: //xxxx.yyy/image.gif(URL)の書き方だと、
画像が自サーバ内にあるにもかかわらず、
わざわざ apache のコネクションを介して画像を取得するのです。
これが apache の不明なログの正体でした。
(問題のPHPソースでは、URL形式を引数にしていました。)
言い換えれば、apache のコネクションを無駄に張っていたのです。
もう少し詳しく説明しましょう。
PHPのページにアクセスする際、そのページ内で、
画像(自サーバ内)のサイズ取得のため getimagesize() をコールしていて、
その引数としてURLを指定していると、
本来1個のコネクションで済むはずが、
2個のコネクションを張ってしまうのです。
仮にそのページに、同時に100アクセスされた場合、
apache のコネクションは200になってしまいます。
・ページに対するコネクションが100
・画像に対する(予想外の)コネクションも100
・合わせて200
#【 何が違う? 】
以上を読んで、
「HTML内に img タグがあれば、同じことが起こるじゃないか」
と思われたでしょうが、それとは違います。
その場合は、ページに対するコネクションの「後」に、
画像へのコネクションが発生するからです。
今回 私が見た現象は、ページに対するコネクションの「最中」に、
画像へのコネクションが追加発生するのです。
#【 apache との関係 】
以上に述べた、予想外のコネクションが発生するとなると、
httpd.conf の MaxClients の意味が薄れてしまいます。
なぜなら MaxClients は、外部からの純粋なアクセス数を
予測/計算して決めますが、その1アクセスで
じつは内部的に2アクセス以上 発生するとなれば、
MaxClients が不足することになるのです。
結果、本来 捌ける(さばける)はずのアクセスを
捌けなくなってしまいます。アクセスの待ち行列が増大します。
これが、ブラウザ表示が重くなった理由です。
#【 まとめ 】
結局、getimagesize() の引数を
/var/www/image.gif(ローカルファイル形式)に修正したところ、
apache がリクエストを捌けるようになり、ブラウザ表示が軽くなりました。
プログラマーは、apache 等のサーバやインフラのことなど
あまり意識しない(というか知らない)場合もあると思います。
本番環境の特殊な状態に晒されて、
初めて問題に気づくことが多いです。
結局 地道に、ノウハウを蓄積するしかないですねぇ。