2026年9月10日

2026年9月10日

Nginxのtcp_nopushとtcp_nodelayの違いと設定方法(sendfileとの関係)

2つの設定の結論

設定 既定値 何をするか 推奨
tcp_nopush off sendfile で送るとき、Linux では TCP_CORK(FreeBSD では TCP_NOPUSH)を使い、パケットを満杯にしてから送る sendfile on と組で on
tcp_nodelay on TCP_NODELAY を使い、小さなデータも待たずに送る 既定の on のまま

どちらも http・server・location に書けます(Nginx 公式ドキュメント ngx_http_core_module)。一般的な Web サイトでは、次の3行を http ブロックに書いておけば足ります。

http {
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
}

背景: TCPがデータを送るタイミング

NagleアルゴリズムとTCP_NODELAY

TCP には、小さなデータをすぐに送らず、ある程度まとめてから送る仕組み(Nagle アルゴリズム)があります。回線を小さなパケットで埋めないための仕組みですが、相手側の「遅延 ACK」と重なると、短い応答の送信が待たされることがあります。

TCP_NODELAY はこの Nagle アルゴリズムを止めるソケットオプションです。Nginx の tcp_nodelay は既定で on で、公式ドキュメントによれば、接続が keep-alive 状態に移ったときに有効になります。SSL の接続、バッファしないプロキシ、WebSocket のプロキシでも有効になります。

TCP_CORKとtcp_nopush

TCP_CORK(Linux)は逆に「栓をする」オプションで、有効な間は満杯にならないパケットを送らずにためます。Nginx の tcp_nopush を on にすると、sendfile を使う送信でこのオプションが使われ、公式ドキュメントによれば次の効果があります。

  • 応答ヘッダーとファイルの先頭を1つのパケットで送れる
  • ファイルを満杯のパケットで送れる

「ヘッダーだけの小さなパケット」が先に出ていかなくなるため、パケットの数が減ります。

tcp_nopushが効く場面と効かない場面

tcp_nopush は sendfile を使うときだけ 有効になります(公式ドキュメント)。sendfile の既定値は off なので、sendfile on を書かずに tcp_nopush on だけを書いても働きません。

sendfile() はディスク上のファイルをカーネル内で直接ソケットに送る仕組みです。そのため、使われるのは Nginx がファイルをそのまま返す場面に限られます。

応答の種類 sendfile tcp_nopush
HTTP で返す静的ファイル(画像・CSS・JS) 使われる 効く
HTTPS で返す静的ファイル 通常は使われない(Nginx が OpenSSL で暗号化してから送るため) 通常は効かない
PHP-FPM(FastCGI)やプロキシ先からの応答 使われない 効かない

HTTPS では、OpenSSL 3.0 とカーネルの TLS 機能(kTLS)を組み合わせた構成でのみ sendfile が使えます(Nginx の変更履歴に「OpenSSL 3.0 使用時の SSL_sendfile() 対応」とあります)。kTLS は既定では有効にならないため、多くの HTTPS サイトでは tcp_nopush の効果はほとんどありません。

WordPress で言えば、PHP が生成するページ本体は PHP-FPM からの応答なので対象外で、wp-content/uploads の画像やテーマの CSS・JS を Nginx が直接返すときだけが対象です。設定しても害はありませんが、目に見える速度改善を期待する設定ではありません。

両方onにしても矛盾しない理由

「まとめて送る」tcp_nopush と「すぐ送る」tcp_nodelay は逆の働きに見えますが、Nginx では使われる場面が分かれています。

  • tcp_nopush: sendfile でファイルを送っている間に使われる
  • tcp_nodelay: 接続が keep-alive 状態に移ったとき(応答を送り終えて次のリクエストを待つとき)などに使われる

ファイルを送る間はパケットを満杯にして数を減らし、応答の最後の小さな部分は待たずに送る、という組み合わせになります。そのため、両方を on にするのが一般的です。

tcp_nodelay off にすると、keep-alive の接続で小さな応答が待たされる原因になりうるため、特別な理由が無ければ既定の on から変えないでください。

設定手順

1. 現在の設定を確認する

配布元によって既定の nginx.conf は違います。たとえば Nginx 公式の Docker イメージ(2026年10月時点の stable)では、sendfile on; が有効で #tcp_nopush on; はコメントになっています。読み込まれている設定全体から確認します。

sudo nginx -T 2>/dev/null | grep -nE 'sendfile|tcp_nopush|tcp_nodelay'

2. 設定を書く

/etc/nginx/nginx.conf の http ブロックを編集します。すでに同じ指令がある場合は、二重に書かずに値を直します(同じブロックに同じ指令を2回書くと、nginx -t が "sendfile" directive is duplicate のようなエラーで止まります)。

http {
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;

    # ... 既存の設定 ...
}

動画や大きなファイルの配信場所だけに付けたい場合は、location に書くこともできます。

location /video/ {
    sendfile   on;
    tcp_nopush on;
}

3. 構文を確認して反映する

Nginx を止める必要はありません。構文を確認し、問題が無ければ設定を読み込み直します。

sudo nginx -t
sudo systemctl reload nginx

nginx -t が syntax is ok と test is successful を表示しない場合は、反映せずに表示された行を直します。

4. 反映後を確認する

# 反映された値
sudo nginx -T 2>/dev/null | grep -nE 'sendfile|tcp_nopush|tcp_nodelay'

# 静的ファイルが正常に返ること
curl -sI https://example.com/wp-includes/js/jquery/jquery.min.js | head -n 1

注意点

  • 共有フォルダーやネットワークファイルシステム: 仮想マシンの共有フォルダーなどでは sendfile で古い内容が返る問題が知られています。開発環境でファイルを変えても反映されない場合は、その環境だけ sendfile off; にします(この場合 tcp_nopush も効かなくなります)。
  • 効果の測り方: 速度への影響は回線やファイルの大きさで変わります。変更前後で同じ条件のアクセスを比べ、数値で確かめてから残すか決めてください。
  • directio との関係: directio を使う設定では、その対象のリクエストで sendfile が使われなくなります(公式ドキュメント)。

まとめ

  • tcp_nopush は sendfile で送るときだけ働き、ヘッダーとファイルの先頭をまとめ、満杯のパケットで送る。既定は off。
  • tcp_nodelay は Nagle アルゴリズムを止める。既定は on で、keep-alive や SSL の接続で使われる。
  • 一般的には sendfile on; tcp_nopush on; tcp_nodelay on; の組み合わせでよい。
  • HTTPS(kTLS なし)や PHP の応答では sendfile が使われないため、tcp_nopush の効果は限られる。
  • 変更後は nginx -t と systemctl reload nginx で反映し、nginx -T で値を確かめる。

sendfile 自体の設定は Nginxのsendfileとtcp_nopushを有効にする方法、nginx.conf の全体像は nginx.confの基本設定 も参照してください。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲