PHP
Apache
画像処理

気を付けよう getimagesize() の引数に

本記事は、前の記事

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 等のサーバやインフラのことなど

あまり意識しない(というか知らない)場合もあると思います。

本番環境の特殊な状態に晒されて、

初めて問題に気づくことが多いです。

結局 地道に、ノウハウを蓄積するしかないですねぇ。