Хорошо, это исключаем.
В идеале хотелось бы получить минимальный конфиг, который воспроизводит
проблему, а также способ порождения клиентских запросов, который к ней
приводит.
Скажите, вы можете видеть эту проблему просто запрашивая в цикле этот ресурс
при помощи, например curl (с поддержкой HTTP/3) ? Или в браузере?
Если нет, то надо получить полный лог quic/udp соединения с самого начала.
Упрощённо, HTTP/3 работает так: есть некое основное UDP ‘соединение’, внутри
которого бегают независимые стримы: несколько управляющих и стримы запросов.
Как читать логи quic:
- найдите ваш запрос, например:
2024/01/29 13:06:29 [debug] 1765202#1765202: *7 http3 request line: “GET /system/ava.png HTTP/3.0”
в данной строке мы видим GET запрос по HTTP/3 протоколу для файла ava.png.
*7 - это номер соединения, назначенный QUIC-стриму запроса.
- Найдите момент порождения этого стрима:
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic stream id:0x0 create
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 posix_memalign: 00005568371BEDF0:512 @16
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 posix_memalign: 00005568371D7560:16384 @16
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 reusable connection: 0
2024/01/29 13:06:29 [debug] 1765202#1765202: *7 add cleanup: 00005568371D7620
…
2024/01/29 13:06:29 [debug] 1765202#1765202: *7 quic init stream
Найдите первое появление соединения *7 перед выводом ‘quic init stream’;
это будет строка ‘add cleanup’, а перед ней строка ‘quic stream id 0x…
create’; В данном пример это соединение *2.
- Вот всё это соединение *2 нам и надо проанализировать.
Можно посмотреть, как завершилось quic соединение *2,
т.к. всё относящееся к QUIC протоколу происходит в рамках этого соединения:
Если поискать ‘quic close handler’, то мы увидим начало закрытия этого
соединения.
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic frame rx app CONNECTION_CLOSE err:0 ft:0
…
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic close handler
…
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic close initiated rc:0 c:00007FD01900F200
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic close immediate term:0 drain:1 error:1 “”
Например, здесь мы видим, что клиент прислал фрейм CONNECTION_CLOSE,
который породил процесс закрытия соединения на сервере; начинают закрываться
все стримы в этом соединении:
…
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic stream id:0x2 cleanup
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic stream id:0x2 close
…
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic stream id:0xa cleanup
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic stream id:0xa close
…
В итоге, соединение закрывается окончательно:
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic close resumed rc:0 c:00007FD01900F200
2024/01/29 13:06:29 [debug] 1765202#1765202: *2 quic close completed
В случае ошибок уровня протокола на сервере, то в дебаг-логе будет какая-нибудь
ошибка. Если же ошибка произошла на клиенте, то он может прислать её описание
в CONNECTION_CLOSE фрейме, с указанием типа фрейм, который её породил.
К сожалению, не всегда клиент присылает описание ошибки, которая, по его
мнению произошла.