画像がない場合にNoImage画像に切替えたい場合がたまにありますが、
サーバ側で行うべきか?プログラム側で行うべきか?プログラムを使う場合もphp?Javascript?といった様々な方法があり、悩ましいことがあります。
そこで、今回nginxを使った画像切替を実装してみて、
他の方法との違いを比べてみたいと思います。
目次
Nginxでの実装方法
nginxに「try_filesディレクティブ」というものがありますので、こちらを使ってみたいと思います。
try_filesディレクティブ
構文 | try_files ファイルパス … 転送先URI; |
ry_files ファイルパス … =HTTPステータスコード; | |
デフォルト値 | なし |
コンテキスト | server, location |
解説 | 指定されたファイルパスが存在する場合はその内容を返し、存在しない場合は最後に指定した転送先URIにリダイレクトする |
server {
(略)
location /img/ {
try_files $uri /img/noimage.jpg;
}
}
これで、画像がないときには、/img/noimage.jpg
に転送されて、noimage.jpgが表示されていることが確認できました。
次は画像がないときにステータスコードを404で返す記述です。
server {
(略)
location /img/ {
try_files $uri =404;
}
}
ステータスコード404で返されているのが確認できました。
今回nginxを使ってno image画像に切替える処理を行いましたが、
プログラムで実装するより遥かに簡単に実装できる印象です。
実際にパフォーマンスはどうなんでしょうか?
abコマンドを使って、試してみたいと思います。
比較材料として、php方式とjavascript方式を用意して比較してみます。
php
<p>
<?php for($i=0; $i<=100; $i++): ?>
<img src="<?php echo chengeImage(); ?>" />
<?php endfor; ?>
</p>
<?php
/**
* 画像切替
*/
function chengeImage() {
$targetImg = dirname(__FILE__) . '/img/hoge.jpg';
if (file_exists($targetImg)) {
return '/img/hoge.jpg';
} else {
return '/img/noimage.jpg';
}
}
?>
javascript
<p>
<?php for($i=0; $i<=100; $i++): ?>
<img src="hoge.jpg" onerror="this.src='/img/noimage.jpg';" />
<?php endfor; ?>
</p>
nginx
<p>
<?php for($i=0; $i<=100; $i++): ?>
<img src="/img/hoge.jpg" />
<?php endfor; ?>
</p>
これらを用意して、abコマンドでベンチマークしてみます。
負荷が低い場合
$ ab -n 1000 -c 100 http://www.example.jp/
Requests per second
回数 | php | nginx | js |
---|---|---|---|
1 | 234.97 | 318.76 | 211.43 |
2 | 249.08 | 224.96 | 269.88 |
3 | 226.11 | 287.98 | 243.55 |
4 | 283.83 | 239.12 | 247 |
5 | 240.17 | 279.58 | 273.9 |
6 | 247.38 | 226.21 | 298 |
7 | 233.63 | 247.58 | 259.63 |
8 | 286.77 | 213.67 | 270.65 |
9 | 213.98 | 304.32 | 273.99 |
10 | 306.53 | 237.08 | 260.47 |
平均 | 252.245 | 257.926 | 260.85 |
ほとんど違いはありませんでした。
Javascript方式は画像の切替はブラウザに渡ってから行うため、
abコマンドでのベンチマーク時点では切替処理を行っておりません。
このベンチーマークの段階ではHTMLを出力しているだけですので、当然早くなります。
負荷を高くした場合
$ ab -n 1000 -c 200 http://www.example.jp/
Requests per second
回数 | php | nginx | js |
---|---|---|---|
1 | 137.08 | 78.41 | 93.48 |
2 | 54.95 | 142.52 | 49.11 |
3 | 48.2 | 137.39 | 68.13 |
4 | 53.51 | 177.05 | 283.74 |
5 | 72.97 | 111.44 | 296.48 |
6 | 102.04 | 96.66 | 77.17 |
7 | 69.59 | 74.47 | 55.25 |
8 | 142.2 | 147.74 | 139.5 |
9 | 46.1 | 216.79 | 309.66 |
10 | 53.76 | 289.3 | 142.46 |
平均 | 78.04 | 147.177 | 151.498 |
Failed requests(リクエストが失敗した回数)の平均値
php | nginx | js |
---|---|---|
10.8 | 3.5 | 0.2 |
php方式では処理が追い付かずエラーが出始めました。
nginxもHTMLを出力しているだけのJavascript方式にはやや劣りますが、そこそこいい勝負をしています。
負荷にも強そうです。
nginxでNoImage画像切替処理を行うと実装も簡単で、パフォーマンスもそこそこよさそうです。
選択肢の一つとして、参考になればと思います。