さくらのクラウド ウェブアクセラレータ (CDN) ＋ オリジン nginx で gzip圧縮・非圧縮コンテンツを出し分けてキャッシュ配信

# CDNサービス利用時の転送量削減
アウトバウント側転送量が従量課金対象のCDNサービスを利用する場合に、
圧縮・非圧縮を出し分けてキャッシュ配信することで、転送量が削減でき、課金額を減らすことができます。

# この記事で試した設定の配信イメージ

この記事では、
・オリジンのWebサーバ「**[nginx](https://www.nginx.co.jp/)**」
・ CDNサービス「**[さくらのクラウド ウェブアクセラレータ](https://www.sakura.ad.jp/services/cdn/)**」
の組み合わせにて、
クライアントが圧縮に対応しているかどうか（Accept-Encodingの値）で、
gzip圧縮・非圧縮を出し分けてキャッシュ配信を行う設定を試してみた内容を書きました。

#### 試した配信の概要
```
クライアント
　↓  ↑ 
ウェブアクセラレータ
 　( sample.css : リクエスト毎の、Accept-Encodingの値で判定して、圧縮・非圧縮を出し分けてキャッシュ配信 )
　↓　↑ 
オリジン（nginx/1.21.0）
```

# ウェブアクセラレータ (CDN) の設定

「**[さくらのクラウド ウェブアクセラレータ](https://www.sakura.ad.jp/services/cdn/)**」の場合、
`Varyヘッダでのコンテンツのキャッシュを保持する設定`の有効・無効を「**Varyサポート機能**」を使って設定します。（`デフォルト：無効`）

設定するサイトの`「Varyサポート」のチェックボックスを有効`に設定します。

→ 詳細：[Varyサポート機能の利用 | ウェブアクセラレータ | さくらのクラウド ドキュメント](https://manual.sakura.ad.jp/cloud/webaccel/manual/settings-vary.html)

Accept-Encoding の正規化については、ウェブアクセラレータの場合、「gzip」「非圧縮」の2種類のみがオリジンに渡る仕様。

> Accept-Encoding の正規化（ノーマライズ）仕様についてウェブアクセラレータの仕様として、クライアントのリクエストヘッダ「Accept-Encoding」の値は正規化（ノーマライズ）されます。ウェブアクセラレータからオリジンには、「gzip (Accept-Encoding:gzip)」か「非圧縮 (Accept-Encodingなし)」の2種類のみが、リクエストヘッダとして送られます。
> 
> [Varyサポート機能の利用 | ウェブアクセラレータ | さくらのクラウド ドキュメント](https://manual.sakura.ad.jp/cloud/webaccel/manual/settings-vary.html) より


# オリジン nginx の設定

#### nginx 設定例
※今回は、gzip関連の設定を 一律 location ディレクティブに設定し、「キャッシュ期間」はコントロールパネルで設定しました。

``` 
location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    gzip on;
    gzip_types text/plain text/css text/xml application/json application/javascript;
    gzip_vary on;
    gzip_proxied　any;
}
```

http , server , location のいずれかのディレクティブに設定

・**gzip**
　http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip
　レスポンスのgzip有効化の設定。
　デフォルト：gzip off; (無効)
　`設定例：gzip on; (有効)`

・**gzip_types**
　http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_types
　gzip圧縮対象のコンテンツタイプの設定。
　デフォルト：gzip_types text/html;
　`設定例：gzip_types text/plain text/css text/xml application/json application/javascript; `

・**gzip_vary**
　http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_vary
　gzip, gzip_static, gunzip が有効な場合に、レスポンスヘッダの「`Vary：Accept-Encoding`」の挿入の無効／有効の設定。
　デフォルト：gzip_vary off; (無効)
　`設定例：gzip_vary on; (有効)`

・**gzip_proxied**
　http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_proxied
　プロキシされている(リクエストヘッダにViaヘッダが存在する場合)リクエストの応答をgzip化するかどうかを、リクエスト・レスポンスの内容で判定する設定。
　デフォルト：gzip_proxied off; (プロキシされているリクエストの応答は、すべてgzip無効)
　`設定例：gzip_proxied any; (プロキシされているリクエストの応答は、すべてgzip有効)`

　※ ウェブアクセラレータからオリジンへのリクエストには`Viaヘッダが存在するため、設定しておく必要があります`。


#### gzip圧縮・非圧縮の出し分け配信を試した

(1) `「Accept-Encoding」未指定`で複数回アクセス → `非圧縮コンテンツ` がキャッシュ配信 (ボディサイズ: 80574 bytes)

```
$ curl -v https://******.user.webaccel.jp/sample.css
...(略)...
< HTTP/2 200
< server: nginx
< date: Tue, 11 Jan 2022 08:03:56 GMT
< content-type: text/css
< content-length: 80574
< last-modified: Sun, 22 Aug 2021 02:31:02 GMT
< etag: "6121b6e6-13abe"
< accept-ranges: bytes
< cache-control: s-maxage=3600
< age: 2
< via: http/1.1 sv16-osk01-jp (ApacheTrafficServer-second [uScHs f p eN:t cCHp s ]), http/1.1 sv13-osk01-jp (ApacheTrafficServer-first [uScMsSfWpSeN:t cCMpSs ])
< x-webaccel-origin-status: 200
< vary: Accept-Encoding
< x-cache: HIT
...(略)...
```

(2) `「Accept-Encoding: gzip」指定`で複数回アクセス → `gzip圧縮コンテンツ` がキャッシュ配信 (ボディサイズ: 13704 bytes)

```
$ curl -H "Accept-Encoding: gzip" -v https://******.user.webaccel.jp/sample.css --output ./sample.css
< HTTP/2 200
< server: nginx
< date: Tue, 11 Jan 2022 08:10:53 GMT
< content-type: text/css
< content-length: 13704
< last-modified: Sun, 22 Aug 2021 02:31:02 GMT
< vary: Accept-Encoding
< etag: W/"6121b6e6-13abe"
< content-encoding: gzip
< cache-control: s-maxage=3600
< age: 4
< via: http/1.1 sv16-osk01-jp (ApacheTrafficServer-second [uScHs f p eN:t cCHp s ]), http/1.1 sv11-osk01-jp (ApacheTrafficServer-first [uScMsSfWpSeN:t cCMpSs ])
< x-webaccel-origin-status: 200
< x-cache: HIT
...(略)...
```

##### 非圧縮 → gzip圧縮後のボディサイズの差分

この実行例の場合は、
` 80574 bytes → 13704 bytes ( 13704.0 / 80574 = 0.1700796783081391 )`
` 圧縮率 約17% (削減率 約83%) ` となりました。