先月、オールアバウトのサービス全般で使用している、画像のリサイズシステムのリプレイスを行いました。
今まで負荷を懸念してリアルタイム変換は行っていなかったのですが、スマートフォンなど画像容量にシビアな端末が中心になったこともあり、 このタイミングでリアルタイムでリサイズできるシステムを構築することにしました。
また、トラフィックの多いサイトでは画像の転送量がかなりの金額になるということもわかりました。特にアクセスの多い画像だと1ヶ月あたり1万円以上の転送量が掛かっていることなど、非常に興味深い数字も見ることができました。
オールアバウトのサービスたち
- 総合情報サイトAll About
- CafeSnap (iOS/Android向けアプリ)
- All Aboutまとめコンテンツ
- All About News Dig
- For M
- All About Japan
- その他いろいろ
旧構成
インフラ
- EC2(m3.large) x 2
- ①リクエストを受ける
- ②変換後の画像があるか確認
- ③なければオリジナルを取得して、クライアントに返却
- ④変換のジョブをSQSに登録
- EC2(m3.xlarge) x 1
- ⑤バッチでキューを取得
- ⑥オリジナル画像を取得し、リサイズ
- ⑦変換後の画像をS3にアップロード
- SQS
- S3(変換後画像の保存用)
- CDN(Akamai)
- S3 or NFS(バックエンドの画像サーバー)
リサイズに使っていたもの
- PHPで書かれたアプリケーション
- ImageMagick
問題点
- 複雑なインフラ構成
- トラブルの時に原因を追いにくい
- インフラコストがかさむ
- リアルタイムじゃない
- SPなどでは表示速度などに関わる
- 画像がメモリを圧迫し、アプリがクラッシュする
- 高スペックのサーバーが必要
- PHPでの処理に向いていないため、サーバースペックでカバーする必要があった
新構成
インフラ
- EC2(c4large) x 2
- ELB x 1
- CDN(Akamai)
- S3 or NFS(バックエンドの画像サーバー)
リサイズに使っているもの
- nginx1.8.1
- nginx_small_light
- ImageMagick
- http_perl_module
- nginx.confだけではできない、変換サイズチェックなど
負荷
- 現状1台あたり、ピーク時で20req/sec
- CPU負荷10~30%
- メモリは全然使わない。4GBで十分。
- ベンチマークでは、80req/secまでは耐えられそう
コスト
- AWSのコスト削減
- 画質チューニングによるCDNのコスト削減
Tips
- 理由がない限りはpngは避け、jpgを使うべき
- 900x600の画像で、pngをjpgにするだけで1.5→0.35MBくらいに減る
- 画像のリサイズ処理はwidth/height最低限片方は指定するべき
- 画質の変更のみだと殆ど容量削減が見込めない
- 画質は90くらいが妥当?GitHubやBitbucketの画像差分が便利(2-up/Swipe/Onion Skinの部分)
- jpeghintは有効にする
- オリジンの画像サーバーが複数ある場合は、リクエストのURLパスの特定の部分から、nginxのconf内で分岐して振り分ける
- http-headerのキャッシュ時間はサービスごとに適切に設定すると、転送量削減につながる
nginx.confの一部例
add_header Cache-Control "public";
expires 1M;