WEB高速化をおこなうためには、コンテンツサイズを極力小さくできる圧縮配信が有効です。コンテンツ圧縮で有名なのはGzipによる圧縮配信ですが、Gzipよりも圧縮率が高いBrotliの概要について、またCDNと同時利用した場合の留意点を掲載いたします。
Brotliとは?
Brotli(ブロトリ)はGoogleがファイルサイズをさらに縮小するために開発したオープンソースの新しいLZ77アルゴリズムをベースとした圧縮アルゴリズムです。日本では馴染みが少ない読み方ですが、由来はスイスで“小さなパン”を意味する「Brotli」(ドイツ語)となっています。
既に「RFC 7932」の一部としてIETFによって定義されており、WOFF(Web Open Font Format) 2.0のフォント形式での圧縮方式の一部として作られたものが他のコンテンツ圧縮にも使えるよう汎用化されました。
Zopfliより圧縮パフォーマンスが高い
Googleは2013年にgzipに変わるZopfliという圧縮アルゴリズムをリリースしていますが、Brotliは Zopfliに比べて圧縮率が20〜26%向上し大幅に高速化できる技術となっています。
Brotliの仕組み
そもそも、コンテンツ圧縮とは何故圧縮されるのかすこしおさらいしてみましょう。
※コンテンツ圧縮の仕組みについてはこちら
たとえば以下のようなテキストがあったとします。
圧縮前テキスト
「おれのものはおれのもの、おまえのものもおれのもの」
このテキストの場合、「おれのもの」のように同じフレーズ(文字列)がある場合は、それらを以下の様に出現場所と文字数を置き換えて容量を抑えています。
圧縮後テキスト
「おれのものは6,5、おまえ10,3も9,5」
Brotliの圧縮方式
コンテンツ圧縮はハフマン法 と 辞書式 があるのですが先ほどの例のように Brotli は辞書式において122MBの大容量辞書を利用し、頻出する単語パターンの圧縮を効率化しています。122MBにも及ぶ辞書には、英語、スペイン語、中国語、ヒンディー語、ロシア語、アラビア語を含む13504語の単語または音節で使用される一般的なフレーズ、特にHTMLおよびJavaScriptが含まれているためWEB業界では高い圧縮率を誇っているようです。
また、gzipは32KBの固定ウィンドウを使用しますが、Brotliは1KBから16MBのスライディングウィンドウを使用します。これは、BrotliがCWNDとRWNDを最適化し大きな圧縮ファイルをさらに効率的に配信できることを意味します。
Brotliとgzipの圧縮率・速度比較
コンテンツ圧縮=gzipと言えるほどスタンダードとなりつつあるgzipとBrotliはどの程度圧縮比率が変わるのかは以下の通りです。
こちらは各種JSライブラリを対象に同じ圧縮率でgzip Zopfli Brotliを比較した表です。
gzipの圧縮率9よりBrotli圧縮率5のほうがコンテンツサイズが小さくなっています。元ファイルが大きければ大きいほどBrotliの効果が高くでています。
Brotliの圧縮速度は高速
圧縮速度については、高い圧縮率を誇っているZopfliと比べるとBrotliは6倍高速に圧縮することが出来ます。gzipと比べてみてもそれほど変わらないため、圧縮レベルは5で設定すべきでしょう。
Brotliの対応状況
Brotliはgzip圧縮と同様に、クライアント側とWEBサーバー両方Brotli圧縮に対応していなければいけません。クライアント側とサーバー側の対応状況は以下の通りです。
クライアント側Brotli対応状況
Can I useで確認すると以下の通りでした。ただし、いずれもHTTPSでの通信時のみとなります。
サーバー側Brotli対応状況
2017年12月時点で主なWEBサーバーとしては以下の通り対応しています。
Apache(httpd 2.4.26からmod_brotliが利用可能)
コンパイル時に–enable-brotliと指定して下さい。
また、–with-brotli=/usr/local/lib にてbrotliのライブラリパスを指定する必要があります。
brotliライブラリのインストールは以下のGITからソースをダウンロードしてコンパイルして下さい。
https://github.com/google/brotli.git
Nginx
以下のngx_brotliを展開し ngx_brotli && git submodule update –initコマンドを実行後、
–add-module=ngx_brotli を追加しNginxをコンパイルする事によって有効化できます。
https://github.com/google/ngx_brotli
Microsoft IIS
オフィシャルでサポートはされていませんが、コミュニティモジュールを導入することにより対応します。
https://www.iis.net/downloads/community/2016/03/iis-brotli
Node.js
こちらもIISと同様にコミュニティモジュールを導入することにより対応します。
https://www.npmjs.com/package/shrink-ray
PHP
PHPでも拡張モジュールによって、brotli圧縮に対応しています。
※この手の内容はサーバーサイドで実行したほうがいいでしょう。
https://github.com/kjdev/php-ext-brotli
Brotliはどのように対応可否を決めているのか
gzip圧縮の場合、Accept-Encodingヘッダーによってクライアント側からサーバーに通知していました。
Brotliも同じように、Accept-Encoding ヘッダーの中身に br という識別名を入れてサーバー側に通知します。サーバー側もBrotliで圧縮コンテンツを提供した場合、content-encoding の中身にbrという識別名を入れてレスポンスします。
Brotli対応CDNについて
さて、CDNを使った場合このような圧縮はどうなるのでしょうか。海外でもクライアントの対応が進むにつれBrotli対応CDNとうのがでてきました。しかし、これはCDN側でコンテンツをBrotli圧縮するのではなくあくまで先ほどのbrというヘッダーをオリジンサーバーに透過させる対応が可能ということです。そのため、Brotliに対応させるためには同時にオリジンサーバー側での対応も必要となります。
CDNはAccept-Encodingを正規化する
CDNはキャッシュキーとして Accept-Encoding をベースにしますが、弊社で10万リクエストのサンプルから Accept-Encoding の内容を調査した所、なんと40以上のパターンがありました。これらのことから、CDNはキャッシュHITさせやすいようにAccept-Encoding の中身を正規化し特定の圧縮フォーマット(大概の場合はgzip)に変換します。そのため、たとえオリジンサーバーでBrotliに対応したとしてもCDNがBrotliに対応していない場合結局gzipで圧縮配信されてしまいます。
Brotli対応CDN側の動き
Brotli対応CDNでは様々な動作があります。たとえば、CDNの設定でBrotliを有効にするとリクエストヘッダーAccept-Encoding:br をオリジンサーバーに透過させ、Brotli圧縮をオリジン側に任せます。こちらはオリジンサーバーがBrotli圧縮に対応していることが必須となり、対応していない場合は圧縮配信が行われないといったデメリットがあります。
このようなことから、弊社CDNはAccept-Encoding 内の文字列に対して以下の通り優先順位をつけました。 br > gzip > deflate
そしてBrotliに対応できるクライアントからアクセスがきた場合で、且つgzipにも対応している場合はヘッダーを正規化後、br gzip deflateをオリジンサーバーに透過させます。Brotliにしか対応していないクライアントを考慮すべく、従来のGzip圧縮・非圧縮ファイルは1つのキャッシュとし、Brotliはこれらとは別のキャッシュとして保存しています。
これによりBrotli対応の場合はオリジンサーバー側でBrotli圧縮されたコンテンツがCDNでキャッシュされ、その他のクライアントについてはGzip圧縮されたコンテンツが配信されます。
まとめ
とっても素晴らしい圧縮率を誇るBrotli。Googleは2013年に開発した圧縮アルゴリズム「Zopfli」と比較すると、20〜26%圧縮率が向上したと表明しています。
2017年後半6ヶ月の弊社CDNトラフィックのうち約80%がBrotliに対応したクライアントから着信があり、20%はgzipを使用しています。ブラウザーの対応状況も進んできているためGzipにかわる圧縮配信のスタンダードとなる日も近いかもしれません。
CDNを通したBrotli圧縮については、gzip圧縮と同様にキャッシュの持ち方やヘッダーの取り扱いが重要となってきます。2017年12月現在、国内で対応しているCDNベンダーは存在しませんがWEBサーバー側の実装がスタンダードとなってくれば対応したCDN事業者も増えてくるものと思われます。