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の基本設定 も参照してください。