17 January

[Nginx] Как победить response_status = 0

System administrationNginx
🔥 Technotext 2020
Tutorial
Статья из разряда «заметки на полях».

TL:DR:
http2_max_field_size 8k; # всех спасет!


На одном из проектов, после изменения некоторой внутренней логики бекенда, начал наблюдать странный response_code в логах, а именно — 0. В логах выглядит примерно так:

{
  "timestamp": "2020-01-17T08:41:51+00:00",
  "remote_addr": "zzz.zzz.zzz.zzz",
  "request_time": 0,
  "upstream_response_time": "",
  "upstream_header_time": "",
  "http_accept_language": "-language",
  "response_status": 0,
  "request": "",
  "host": "example.com",
  "upstream_addr": "",
  "http_referrer": "",
  "request_length": 5854,
  "bytes_sent": 0,
  "http_user_agent": ""
}

Чтение документации и гугление на данную тему дало ровным счетом ничего — т.к. утверждается, что такое поведение возникает, когда клиент закрыл соединение не передав заголовки. Ну и разная экзотика с размером буффера для wsgi_, что в нашем случае не подходило от слова «никак».

В целом, решили, что проблема — не проблема, с учетом того, что на наших объемах оно совершенно не критично.

Ровно до того момента, пока меня не озадачили следующей проблемой: в некоторых случаях ссылки без проблем открываются по http, но совершенно отказываются работать по https, выдавая чудесное: Connection #0 to host example.com left intact
curl: (52) Empty reply from server

В логах отследить эту штуку удалось только по IP — ни реквеста, ни каких-либо других данных, как видно из примера выше — нет. Только пресловутый статус 0, но я-то знаю, что запрос я не прерывал! Начал ковырять, что же может пойти не так. А все оказалось очень просто:

listen 443 ssl http2 backlog=8192;

Ну так вот — если использовать http2 для ssl-соединений, то недостаточно просто конфигурять буферы запроса, конфигурять их надо и в ngx_http_v2_module, а именно:

Синтаксис:	http2_max_field_size размер;
Умолчание:	http2_max_field_size 4k;
Контекст:	http, server

Ограничивает максимальный размер заголовка запроса, сжатого при помощи HPACK. Ограничение применяется в равной степени как к имени, так и к значению. Если применяется кодирование Хаффмана, то фактический размер распакованных строк имени и значения может быть больше. Ограничение по умолчанию подходит для большинства запросов.

В общем, это оно. А все почему? Потому что длина ссылки была большой — больше, чем те самые 4k.

Выставив его в, например, 8kb (или столько, сколько наверняка хватит) — решаем проблему.
Такие дела.
Tags:nginxhttp2sslresponse_status=0
Hubs: System administration Nginx
+25
5.3k 46
Comments 4