nginxのtcp_nodelayディレクティブは設定しなくても良い
「nginx実践入門」お買い上げ頂きありがとうございます。レビュー等読ませて頂いていると、気になるところがあったので補足です。
- 作者: 久保達彦,道井俊介
- 出版社/メーカー: 技術評論社
- 発売日: 2016/01/16
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
tcp_nodelayは設定しなくても良い
tcp_nodelay
ディレクティブはTCP_NODELAY
オプションを付与するための設定です。これはデフォルトで有効ですし、競合しそうなTCP_NOPUSH
やsendfile
ともうまいこと使えるように実装されています。そのため明示的にoff
にすることは殆どないでしょう。このディレクティブがデフォルトで有効になったのはnginx 0.3.61の事なので、これより古いバージョンを使っている環境はあまり想像できません。
tcp_nodelayは何をするのか
さて本題はもう終わったのですが、tcp_nodelay
ディレクティブは何を設定するディレクティブなのか簡単に説明しておきます。tcp_nodelay
ディレクティブが有効であるとき、ソケットにTCP_NODELAY
オプションが設定されます。TCP_NODELAY
オプションはNagleアルゴリズムを無効にするためのオプションです。
NagleアルゴリズムはRFC896の著者であるJohn Nagle氏の名前から名付けられたアルゴリズムであり、このRFC中で説明されている"small-packet problem"を回避するためのアルゴリズムです。Nagleアルゴリズムでは、小さなパケットの送信を防ぐため、データを一旦バッファリングして大きなパケットにしてから送信しようとします。そのため、小さなパケットを送信しようとしたとき、バッファリングがタイムアウトするまで(調べてないけど200ms?)遅延が発生してしまうことになります。TCP_NODELAY
を有効にすると、このバッファリングを無効にすることで、遅延を最小化することができます。
前述したように、nginxではキープアライブ接続の場合デフォルトでTCP_NODELAY
を設定します。これにより、パケット到着までの遅延を短くすることを実現しています。特にTLSのハンドシェイクなどではかなり効いてくるはずです。
tcp_nopushディレクティブと組み合わせるとどうなるのか
さて、本書ではtcp_nopush
ディレクティブを有効にすることを推奨しています(詳しくは3.4節をごらん下さい)。このオプションはパケットをまとめることで送信するパケット数を最小化するためのオプションです。つまりTCP_NODELAY
と逆の動きをするように見えます。ではtcp_nopush
ディレクティブとtcp_nodelay
ディレクティブの両方を有効にしても大丈夫なのでしょうか?
nginxではTCP_NOPUSH
が有効になるのはsendfile
を利用する場合のみです。ソースコードを見ると、LinuxではTCP_CORK
を有効にするまえにTCP_NODELAY
が有効であれば無効にするように動作します*1。そのため、両方のディレクティブが有効のままでも問題はありません。
設定しないといけないディレクティブは意外と少ない
nginxには数百ものディレクティブがあり、書籍中で取り上げたのはそのうちの一部です。静的ファイル配信に使うのであれば、設定する必要があるディレクティブはそれほど多くありません。自分の好みとしては設定する必要がないディレクティブは少ない方が嬉しいです。調べる必要もなくなるし、余計な手間を減らすことができます。ということで書籍中でもそのようなディレクティブは説明自体を省いています*2。
設定しなければないディレクティブが少ないのはnginxの良いところの1つです。tcp_nodelay
ディレクティブはデフォルトで有効なので、明示的に記述する必要はないでしょう。sendfile
とtcp_nopush
ディレクティブは歴史的な事情と環境依存の問題によってデフォルトoff
にされていることが推測できるのですが、通常の使用においては有効にして問題になることは少ないでしょう。ということで書籍で紹介しているようにsendfile
、tcp_nopush
は明示的に有効にすることをおすすめします。
詳しくはnginx Tech Talksで
このあたりの話は2月の勉強会でやろうと思ってるので、是非参加いただければ幸いです。