シナリオ:リソースが突然読み込まれなくなる
Webアプリを構築中、またはページを読み込んでいると、CSSファイル、JavaScriptバンドル、画像など複数のリソースがまったく読み込まれなくなることがあります。ブラウザの開発者コンソールには次のようなエラーが表示されます:
GET https://example.com/assets/main.js net::ERR_HTTP2_PROTOCOL_ERROR
このエラーは404よりも厄介です。404はファイルが存在しないことを意味します。このエラーは、ブラウザとサーバーがHTTP/2で通信を開始した後、通信の途中で何かが壊れたことを意味します。通信チャネル自体が断絶したのです。この曖昧さがデバッグを難しくしています。
なぜこのエラーが発生するのか?
このエラーは複数の原因を包括する汎用エラーです。実際には、主に4つの原因に絞られます:
- **ヘッダーサイズの制限:**クッキーはリクエストヘッダーにまとめて含まれます。アプリが8KBを超えるデータをクッキーに保存している場合、HTTP/2ヘッダーがNginxで許可されているバッファサイズを超えてしまいます。
- **Nginxのプロキシバッファリング:**Nginxがバックエンドをプロキシする際、レスポンスをバッファリングします。デフォルトのバッファ(通常4×8KB)は大きなAPIレスポンスには小さすぎるため、ストリームが途中で終了してしまいます。
- **ディスク容量:**Nginxはオーバーフローした内容を
proxy_tempディレクトリに書き込みます。ディスクがいっぱいになるとその書き込みが失敗し、HTTP/2ストリームもクラッシュします。 - **ソフトウェアの古さ:**1.14以前のNginxはHTTP/2スタックに実際のバグが存在していました。該当バージョンをお使いの場合は、設定変更の前にまずアップグレードしてください。
ステップ1:簡単な対処法(クライアント側)
サーバー設定を変更する前に、まずここから始めてください。ブラウザの状態がこのエラーの原因となるケースは意外と多いです。
ブラウザキャッシュとクッキーをクリアする
膨らんだクッキーは典型的なトリガーです。サイトをシークレットウィンドウやプライベートウィンドウで開いてみてください。そこで読み込めるなら、クッキーが原因です。サイトデータをクリアして再試行してください。
ブラウザ拡張機能を確認する
広告ブロッカー、VPN拡張機能、セキュリティツールはいずれもHTTP/2ストリームに干渉する可能性があります。一つずつ無効化してリロードしてみてください。30秒で済み、一連の問題を除外できます。
ステップ2:サーバー側の修正(Nginx設定)
多くの本番環境では、Nginxの設定が本当の解決策になります。まずヘッダーバッファから始め、必要に応じてプロキシバッファに進んでください。
ヘッダーバッファサイズを増やす
以下のディレクティブをhttp、server、またはlocationブロックに追加します。設定ファイルは通常/etc/nginx/nginx.confまたは/etc/nginx/sites-available/defaultにあります:
http {
# ... 既存の設定 ...
# HTTP/2ヘッダーの許容サイズを増やす
http2_max_field_size 16k;
http2_max_header_size 32k;
# 一般的なヘッダーバッファも増やす
large_client_header_buffers 4 32k;
}
**Nginx 1.25.5以降の注意:**そのバージョンでHTTP/2モジュールが書き直された際に、http2_max_field_sizeとhttp2_max_header_sizeディレクティブは削除されました。それ以降のバージョンでは、large_client_header_buffersのみが必要な設定項目です。
プロキシバッファ設定を調整する
Node.jsやPythonなどのバックエンドをプロキシしている場合、デフォルトバッファはわずか4×8KBと非常に小さいです。500KBのJSONペイロードを返す単一のAPIレスポンスだけで即座に超過してしまいます。バッファがいっぱいになると、NginxはHTTP/2ストリームを切断します。
location / {
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_pass http://your_backend;
}
ステップ3:環境の確認
問題が環境にある場合、設定の修正は効果がありません。確認すべきことは2つです:ディスク容量とNginxのバージョン。
ディスク容量を確認する
Nginxは大きなレスポンスを/var/lib/nginx配下の一時ディレクトリに書き込みます。パーティションがいっぱいになると書き込みが失敗し、HTTP/2ストリームが即座にクラッシュします。以下のコマンドで確認してください:
df -h
100%になっているパーティションは即座に危険信号です。稼働中のサーバーは/var/log/nginx/に1週間でアクセスログが数ギガバイト蓄積されることがあります。ログをローテートまたはクリアして素早くディスク容量を確保してください。
Nginxのバージョンを確認する
初期のHTTP/2実装には実際の安定性バグが存在していました。1.14以前のバージョンは、このエラーに関わらずアップグレードを推奨します。現在のバージョンを確認するには:
nginx -v
2024年時点では、Nginx 1.26.xが現在の安定版ブランチです。メジャーバージョンが2つ以上遅れている場合、アップグレードだけで問題が解決する可能性があります。
ステップ4:動作確認
設定をテストせずにNginxを再起動しないでください。シンタックスエラーがあるとサーバーがダウンします。
sudo nginx -t
正常な結果は次のように表示されます:nginx: configuration file /etc/nginx/nginx.conf test is successful。その後、サービスをリロードします:
sudo systemctl reload nginx
--http2フラグを付けたcurlコマンドでコマンドラインから修正を確認します:
curl -I --http2 https://example.com/assets/main.js
レスポンスにHTTP/2 200が表示されれば成功です。それ以外の場合は、どこかでストリームがまだ失敗していることを意味します。
ネットワークに関するヒントと予防策
プロトコルエラーは、アプリケーションではなくネットワーク層に起因することもあります。たとえばMTUの不一致は、NginxのバッファリングProblemと見分けがつかない形でHTTP/2フレームを断片化することがあります。Nginxの設定をすべて調整してもエラーが続く場合は、VPN、ロードバランサー、CDN層をバイパスした直接接続で問題が再現するかどうかを確認してください。
トラフィックが複数のホップを経由するVPC環境では、サブネットの誤算がルーティングオーバーヘッドを生み出し、プロトコルレベルの障害として現れることがあります。サブネット計算ツールを使うと、Nginxバッファの調整にさらに時間を費やす前に、CIDRレンジが正しいかどうかを確認するのに役立ちます。
まとめると:クッキーは4KB未満に抑え、プロキシバッファは実際のレスポンスサイズに合わせて設定し、Nginxを常に最新の状態に保つこと。この3つを実践すれば、このエラーに悩まされることはほとんどなくなるでしょう。

