Help us understand the problem. What is going on with this article?

nginxパフォーマンスチューニング〜静的コンテンツ配信編〜

More than 3 years have passed since last update.

今回はHTMLやCSS、Javascriptといった比較的軽量な静的コンテンツの配信をnginxでやるケースに絞ってチューニングする際のポイントについて紹介しようかと思います。

(注:worker_rlimit_nofileやsysctl.confのネットワーク周りの設定のような定石的なチューニングについてはあえて解説しないのであらかじめご了承ください。)

コンテンツをgzip圧縮する

何はともあれgzip圧縮です。ネットワーク帯域に比べればCPUリソースなんて安いものです。

# コンテンツをgzip圧縮する
gzip on;

しかし、多くの場合これだけでは十分ではありません。何故ならnginxはデフォルトではContent-Typeがtext/htmlのコンテンツしか圧縮しないためです。圧縮対象のContent-Typeを増やすにはgzip_typesを使います。

# text/htmlはgzip onであれば常に圧縮される
gzip_types text/css text/javascript;

単純なWebサイトであれば上記の設定で十分ですが、場合によってはapplication/jsonapplication/javascriptといったContent-Typeを加えるのもよいでしょう。

また、Apacheのmod_deflateと違ってnginxのgzip圧縮モジュールはgzip_vary on;と書かないとコンテンツをgzip圧縮した際にVary: Accept-Encodingを付加しないので注意しましょう。

コンテンツキャッシュとVaryヘッダとnginx

gzip_staticモジュールで圧縮済みのコンテンツを配信する

「ネットワーク帯域に比べればCPUリソースなんて安いものです」とは言ったものの、やはり配信量が増えてくるとgzip圧縮によるCPUリソースの消費も無視できなくなってきます。

そういった場合に有効なのがgzip_staticです。通常nginxでコンテンツのgzip圧縮を有効にした場合(gzip on)、コンテンツを配信する際に毎回コンテンツのgzip圧縮を行いますが、gzip_staticを有効にすると既に圧縮済みのファイル(e.g. xxx.js.gz)があればそれをそのまま配信します。なのでこの機能を使うとCPUリソースを大幅に節約できます。また、gzip圧縮をサポートしていないクライアントにも配信する場合はgunzipを利用してgzファイルを展開するようにしましょう。

# xxx.(css|js).gzが存在したらそれをそのまま配信する
# また、クライアントがgzip圧縮をサポートしてない場合はgzファイルを展開して配信する
location ~* \.(css|js)$ {
    gzip_static always;
    gunzip on;
}

あと、gzip_staticgunzipを利用するにはnginxのconfigure実行時に--with-http_gzip_static_module--with-http_gunzip_moduleのオプションが必要です。

zopfliでさらに圧縮する

zopfliはgzipやzlibが利用しているdeflate互換の圧縮アルゴリズム(とその実装)です。
deflateと互換性があるのでzopfliで圧縮したコンテンツはdeflateで展開することができます。加えてzopfliはdeflateよりも圧縮率が高い(数%)という利点があります、その反面圧縮にかかるコストはdeflateに比べて非常に高いので、nginxでコンテンツを配信する際に毎回zopfliで圧縮するといったようなことは現実的ではありません。

しかし、gzip_staticを利用しているのであれば話は別です。先述の通りzopfliはdeflateと互換性があります。zoplfliで圧縮したファイルはdeflateで展開可能なのでzopfliで圧縮したgzファイルをgzip_staticで配信すればよいわけです。

expiresでクライアントにキャッシュさせる

コンテンツを圧縮することでネットワーク帯域を節約できるのはよいことですが、もっと帯域を節約できるよい方法があります。それは一度アクセスしてきたクライアントには自身のキャッシュを利用するようにして配信サーバ自体は304を返すようにすることです。

今回は静的コンテンツの配信なのでnginxの場合は以下のようにexpiresを設定するだけで十分でしょう。

expires 30d;

expiresは結構書式がいろいろあってややこしいので詳しくは本家のドキュメントをご覧ください。

open_file_cacheで配信コンテンツのファイル情報をキャッシュする

open_file_cacheを利用するとファイルディスクリプタやサイズ、更新時間といった情報をキャッシュすることができます。

# キャッシュのエントリー数(max)とアクセスがないキャッシュの有効期間を設定
open_file_cache max=100 inactive=10s;

主にファイルのopenやcloseに伴うシステムコールのオーバーヘッドを軽減する効果があります。

cubicdaiya
Tech Lead, Site Reliability
mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした