Apache/Nginxを使用して複数サーバー使用時のETagの設定

ETagとは

キャッシュの有効性確認をするために使われる値です。

  1. データを返すときにETagという値をレスポンスヘッダーで返す
  2. 同じデータにアクセスするときキャッシュしているリクエストヘッダーにETagの値を付与します
  3. サーバーはクライアントから受け取ったETagの値とレスポンス時のETagの値を比較して、異なった場合はステータスコード200で通常通りデータ全てを返却、同じだった場合はステータスコード304(Not Modified)とだけ返します

これにより、304で返すときはデータを返さなくて良いのでダウンロード時間を減らせたり、サーバー側の帯域を減らすことができます。

利点と欠点

Cache-Controlヘッダーと比較した場合、サーバー側でキャッシュが制御できるという利点がありますが、毎回リクエストが飛んでしまうという欠点があります。

ETagを使用する場合

複数台のサーバーで運用する場合、同じファイルをデプロイしたときに各サーバー間で同じETagになるか確認しておく必要があります。

例えばCapistranoでのデプロイの場合下記の様になりました。

Capistranoでのデプロイ

Capistranoでデプロイした時のファイルを stat public/css/style.css でETagに使われる情報を見てみたところ以下の様になりました。 Server1とServer2でSizeとModifyの値が同じなのでどちらのサーバーにアクセスが来ても同じETagを返すことが分かります。

Server1

File: ‘public/css/style.css’
  Size: 16364       Blocks: 32         IO Block: 4096   regular file
  Device: cxxxx/xxxxxd  Inode: 1234567     Links: 1
  Access: (0664/-rw-rw-r--)  Uid: (  505/     app)   Gid: (  505/     app)
  Access: 2017-12-27 19:21:25.656951609 +0900
  Modify: 2017-12-27 19:19:32.000000000 +0900
  Change: 2017-12-27 19:21:25.656951609 +0900
   Birth: -

Server2

File: ‘public/css/style.css’
  Size: 16364       Blocks: 32         IO Block: 4096   regular file
  Device: cxxxx/xxxxxd  Inode: 7654321     Links: 1
  Access: (0664/-rw-rw-r--)  Uid: (  505/     app)   Gid: (  505/     app)
  Access: 2017-12-27 19:21:25.629318890 +0900
  Modify: 2017-12-27 19:19:32.000000000 +0900
  Change: 2017-12-27 19:21:25.629318890 +0900
   Birth: -

Apacheの場合

inode番号を含めると脆弱性に繋がる場合があるのと、複数台運用の場合返すサーバーによって同じファイルでもETagの値が変わってしまうので外します。

OK

FileETag MTime Size

NG

FileETag INode MTime Size
FileETag ALL

Nginxの場合

NginxではETagの設定はon/offしかできないですが、変更日時とファイルサイズのみで決まる様なのでApacheのOKの設定と生成方法が同じになります。

ちなみに

AWSのS3から配信される場合のETagはファイルのハッシュ値になっている様です。おそらくこれがApacheやNginxでできたらベストだと思います。