ApacheWebServerで圧縮転送の設定

この記事は公開されてから半年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS(など)のクラウドサービスでは簡単に構築ができて便利でよいのですがトラフィック転送量は従量課金です。
それならば少しでもコストを抑えたいと考えることも不思議ではないと思います。
ここでは古くからの手法ですがgzip圧縮を用いたトラフィックの軽減についてまとめてみました。

準備

テストを実施するにおいての環境を用意します。

  • サーバ: t2.micro(AWS)
  • ストレージ: gp2(SSD)
  • OS: AmazonLinux2016.03
  • Webサーバ: Apache2.4.18
  • PHP: 5.6.22
  • DBMS: MySQL 5.5
  • CMS: Concreat5

今回のテストサイトはサンプルのデータも適度にあるCMSでConcreat5を利用してみます。
Concreat5のインストールは標準的に行ってあります。

基本的な設定

Configの設定

早速有効にしてみます。

Apacheのドキュメントページにある通り、httpd.confで対象のコンテナに下記を含めます。

AddOutputFilterByType DEFLATE text/html text/plain text/xml 

またサーバの設定として圧縮率についてのログも出力するようにしておきましょう。(こちらもドキュメント通りです)

    DeflateFilterNote Input instream
    DeflateFilterNote Output outstream
    DeflateFilterNote Ratio ratio
    LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
    CustomLog logs/deflate_log deflate 

設定がおわると反映させましょう。

# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

アクセス

早速アクセスしてみましょう。ここでは画像も適度に入ったPortfolioに対してアクセスして計測してみます。
Firefoxをメインとして活用していますので、Firebugのパネルでの確認とします。
比較のためまずはDeflateを有効にする前を確認しておきます。

有効にする前のタイムラインはこんな感じでした。
2016-06-24_11_41_16_deflate
68.7KBのサイズですね。

圧縮を有効にしたタイムラインを確認するとこのような感じになります。
2016-06-24_11_37_48_before
gzip圧縮が有効になると9.3KBのサイズになっています。
(このスクリーンショットでは圧縮とは無関係な水色のDNS resolution timeの時間が増えていて悲しいサンプルになっていますが・・・:-()

HTTPのヘッダも念のため確認しておきましょう。

未対応時
2016-06-24_11_41_42_header

有効時
2016-06-24_11_43_03_deflate_header

ちゃんとブラウザとサーバの双方でgzipを利用する合意が得られていますね。

せっかく設定したログでも圧縮率を確認しておきましょう。


"GET /concrete5/index.php/portfolio HTTP/1.1" 9515/70312 (13%)

13%とのことで、ブラウザからみたものとだいたい一致していますね(当たり前ですけど)。

さらに調子にのってみる

gzip圧縮でコンテンツを送り出すという仕組み上CPUはちょっぴり使うのですが、太い帯域よりもCPUリソースの方が入手しやすいシチュエーションもあるので圧縮レベルをあげて、CSSもJSも圧縮対象としてみます。

DeflateCompressionLevel 9
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript


"GET /concrete5/index.php/portfolio HTTP/1.1" 9375/70312 (13%)
"GET /concrete5/concrete/themes/elemental/css/bootstrap-modified.css HTTP/1.1" 14598/91754 (15%)
"GET /concrete5/application/files/cache/css/elemental/main.css HTTP/1.1" 5370/39755 (13%)
"GET /concrete5/concrete/css/font-awesome.css HTTP/1.1" 4933/21969 (22%)
"GET /concrete5/concrete/blocks/page_list/templates/thumbnail_grid/view.css HTTP/1.1" 295/1107 (26%)
"GET /concrete5/concrete/blocks/search/view.css HTTP/1.1" 159/347 (45%)
"GET /concrete5/concrete/css/jquery-ui.css HTTP/1.1" 7775/43778 (17%)
"GET /concrete5/concrete/js/jquery.js HTTP/1.1" 33199/95957 (34%)
"GET /concrete5/concrete/js/picturefill.js HTTP/1.1" 5153/11807 (43%)
"GET /concrete5/concrete/js/events.js HTTP/1.1" 690/2045 (33%)
"GET /concrete5/concrete/js/underscore.js HTTP/1.1" 4893/14428 (33%)
"GET /concrete5/concrete/js/backbone.js HTTP/1.1" 6635/19262 (34%)
"GET /concrete5/concrete/js/bootstrap/dropdown.js HTTP/1.1" 902/2021 (44%)
"GET /concrete5/concrete/js/bootstrap/tooltip.js HTTP/1.1" 2215/6685 (33%)
"GET /concrete5/concrete/css/app.css HTTP/1.1" 34934/254864 (13%)
"GET /concrete5/concrete/js/bootstrap/popover.js HTTP/1.1" 646/1609 (40%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.js HTTP/1.1" 433/1285 (33%)
"GET /concrete5/concrete/js/app.js HTTP/1.1" 40839/160617 (25%)
"GET /concrete5/concrete/js/jquery-ui.js HTTP/1.1" 51243/191167 (26%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.css HTTP/1.1" -/- (-%)
"GET /concrete5/index.php/ccm/assets/localization/core/js HTTP/1.1" 5325/26448 (20%)
"GET /concrete5/index.php/ccm/assets/localization/jquery/ui/js HTTP/1.1" 467/1283 (36%)
"GET /concrete5/concrete/themes/elemental/images/background.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/images/logo.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/images/bg_toolbar.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/css/fonts/fontawesome-webfont.woff?v=4.2.0 HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/5614/6673/4721/shoes.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/7214/6673/4720/bridge.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/6014/6673/4720/houses.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/3514/6673/4720/mountains.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/1214/6673/4720/subway.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/8014/6673/4720/sunset.jpg HTTP/1.1" -/- (-%)

さすがテキストファイルですね。結構な圧縮が効いているようです。
2016-06-24_14_30_37_level9
2.1MBあった転送量が1.4MBまで軽減できているようです。

おまけ

画像の圧縮

一般的には画像は圧縮が効きにくいので対象とするとCPUがもったいないのでやりませんが、圧縮レベルを9にして画像も対象にしてみるとこんな感じです。


"GET /concrete5/index.php/portfolio HTTP/1.1" 9375/70312 (13%)
"GET /concrete5/application/files/cache/css/elemental/main.css HTTP/1.1" 5370/39755 (13%)
"GET /concrete5/concrete/css/font-awesome.css HTTP/1.1" 4933/21969 (22%)
"GET /concrete5/concrete/js/jquery.js HTTP/1.1" 33199/95957 (34%)
"GET /concrete5/concrete/themes/elemental/css/bootstrap-modified.css HTTP/1.1" 14598/91754 (15%)
"GET /concrete5/concrete/css/app.css HTTP/1.1" 34934/254864 (13%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.css HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/blocks/search/view.css HTTP/1.1" 159/347 (45%)
"GET /concrete5/concrete/blocks/page_list/templates/thumbnail_grid/view.css HTTP/1.1" 295/1107 (26%)
"GET /concrete5/concrete/js/picturefill.js HTTP/1.1" 5153/11807 (43%)
"GET /concrete5/concrete/js/events.js HTTP/1.1" 690/2045 (33%)
"GET /concrete5/concrete/js/underscore.js HTTP/1.1" 4893/14428 (33%)
"GET /concrete5/concrete/js/backbone.js HTTP/1.1" 6635/19262 (34%)
"GET /concrete5/concrete/js/bootstrap/dropdown.js HTTP/1.1" 902/2021 (44%)
"GET /concrete5/concrete/js/bootstrap/tooltip.js HTTP/1.1" 2215/6685 (33%)
"GET /concrete5/concrete/js/bootstrap/popover.js HTTP/1.1" 646/1609 (40%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.js HTTP/1.1" 433/1285 (33%)
"GET /concrete5/concrete/js/app.js HTTP/1.1" 40839/160617 (25%)
"GET /concrete5/concrete/js/jquery-ui.js HTTP/1.1" 51243/191167 (26%)
"GET /concrete5/index.php/ccm/assets/localization/core/js HTTP/1.1" 5325/26448 (20%)
"GET /concrete5/index.php/ccm/assets/localization/jquery/ui/js HTTP/1.1" 467/1283 (36%)
"GET /concrete5/concrete/css/jquery-ui.css HTTP/1.1" 7775/43778 (17%)
"GET /concrete5/concrete/themes/elemental/images/background.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/images/logo.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/images/bg_toolbar.png HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/css/fonts/fontawesome-webfont.woff?v=4.2.0 HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/7214/6673/4720/bridge.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/1214/6673/4720/subway.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/8014/6673/4720/sunset.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/6014/6673/4720/houses.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/5614/6673/4721/shoes.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/3514/6673/4720/mountains.jpg HTTP/1.1" -/- (-%)
"GET /concrete5/index.php/portfolio HTTP/1.1" 9378/70312 (13%)
"OPTIONS * HTTP/1.0" -/- (-%)
"GET /concrete5/concrete/themes/elemental/css/bootstrap-modified.css HTTP/1.1" 14598/91754 (15%)
"GET /concrete5/application/files/cache/css/elemental/main.css HTTP/1.1" 5370/39755 (13%)
"GET /concrete5/concrete/css/font-awesome.css HTTP/1.1" 4933/21969 (22%)
"GET /concrete5/concrete/blocks/search/view.css HTTP/1.1" 159/347 (45%)
"GET /concrete5/concrete/blocks/page_list/templates/thumbnail_grid/view.css HTTP/1.1" 295/1107 (26%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.css HTTP/1.1" -/- (-%)
"GET /concrete5/concrete/js/picturefill.js HTTP/1.1" 5153/11807 (43%)
"GET /concrete5/concrete/css/jquery-ui.css HTTP/1.1" 7775/43778 (17%)
"GET /concrete5/concrete/js/jquery.js HTTP/1.1" 33199/95957 (34%)
"GET /concrete5/concrete/js/events.js HTTP/1.1" 690/2045 (33%)
"GET /concrete5/concrete/js/underscore.js HTTP/1.1" 4893/14428 (33%)
"GET /concrete5/concrete/js/backbone.js HTTP/1.1" 6635/19262 (34%)
"GET /concrete5/concrete/js/bootstrap/dropdown.js HTTP/1.1" 902/2021 (44%)
"GET /concrete5/concrete/js/bootstrap/tooltip.js HTTP/1.1" 2215/6685 (33%)
"GET /concrete5/concrete/js/bootstrap/popover.js HTTP/1.1" 646/1609 (40%)
"GET /concrete5/concrete/blocks/autonav/templates/responsive_header_navigation/view.js HTTP/1.1" 433/1285 (33%)
"GET /concrete5/concrete/css/app.css HTTP/1.1" 34934/254864 (13%)
"GET /concrete5/concrete/js/app.js HTTP/1.1" 40839/160617 (25%)
"GET /concrete5/concrete/js/jquery-ui.js HTTP/1.1" 51243/191167 (26%)
"GET /concrete5/index.php/ccm/assets/localization/jquery/ui/js HTTP/1.1" 467/1283 (36%)
"GET /concrete5/index.php/ccm/assets/localization/core/js HTTP/1.1" 5325/26448 (20%)
"GET /concrete5/concrete/themes/elemental/images/background.png HTTP/1.1" 686/1161 (59%)
"GET /concrete5/concrete/images/logo.png HTTP/1.1" 10803/10798 (100%)
"GET /concrete5/concrete/images/bg_toolbar.png HTTP/1.1" 954/1374 (69%)
"GET /concrete5/concrete/css/fonts/fontawesome-webfont.woff?v=4.2.0 HTTP/1.1" -/- (-%)
"GET /concrete5/application/files/thumbnails/large/7214/6673/4720/bridge.jpg HTTP/1.1" 132165/132952 (99%)
"GET /concrete5/application/files/thumbnails/large/5614/6673/4721/shoes.jpg HTTP/1.1" 115086/115466 (99%)
"GET /concrete5/application/files/thumbnails/large/6014/6673/4720/houses.jpg HTTP/1.1" 199950/200196 (99%)
"GET /concrete5/application/files/thumbnails/large/3514/6673/4720/mountains.jpg HTTP/1.1" 173527/177283 (97%)
"GET /concrete5/application/files/thumbnails/large/1214/6673/4720/subway.jpg HTTP/1.1" 195195/195568 (99%)
"GET /concrete5/application/files/thumbnails/large/8014/6673/4720/sunset.jpg HTTP/1.1" 262235/262547 (99%)

やはりあまり意味のある結果ではなさそうですね。

負荷について

前述のとおり圧縮にはCPUリソースを利用しますのですべてのケースで圧縮が良いかは考慮する必要はあると考えます。
(非力なサーバを利用せざるを得ない場合など)
しかしネットワークの方が優先して解決すべき問題である場合には活用することも検討するとよいと考えます。
また、転送時間が短くなると多くの場合はWebの体感速度向上にも貢献します。
圧縮率が最高の9だとt2.microでは少し重いのですが、インスタンスサイズを少しあげて実験すると次のようなレスポンスが得られるようです。
2016-06-24_14_48_35_instancesize
1.2MBの転送量で920msの転送時間でページが表示できています。

キャッシュ

実際のサービスにおいては当然ブラウザキャッシュが利いてしまえばそもそもの転送が抑えられるので圧縮の転送は最初の1回のみしか有効ではないかもしれません。キャッシュの利用も当然考える必要がありますね。

自分はApache Web Serverとの付き合いはもうかなり長いのですが、いろいろと良い実装のWebサーバもある中でも豊富なモジュールとアイデアで工夫のしがいがあるところは相変わらず面白いソフトウェアですね。

それでは素敵なgzipライフを!

投稿者プロフィール

えんじにあん
インフラ系のエンジニアです。
運用系のスクリプトを書いたり、オートメーションな世界に向かって日々精進しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.

ABOUTこの記事をかいた人

インフラ系のエンジニアです。 運用系のスクリプトを書いたり、オートメーションな世界に向かって日々精進しています。