После включения HTTP / 2 на моем веб-сайте я обнаружил, что производительность резко упала. Скорость загрузки становится намного ниже, а запросы больших изображений блокируют другие вызовы API.
Вот пример веб-страницы, иллюстрирующий эту проблему:
<img src="img.jpg">
<script>
for(var i=0;i<50;i++)
setTimeout(()=>{
fetch('foo.txt');
},i*100);
</script>
(img.jpg
это изображение размером ~ 700 КБ и foo.txt
это небольшой текстовый файл. Все обслуживается прямо из nginx.)
Вот график временной шкалы, когда HTTP / 2 НЕ включен (listen 443 ssl
):
... и когда HTTP / 2 включен (listen 443 ssl http2
):
Вы можете видеть, что HTTP / 2 вызывает большее время загрузки обоих img.jpg
и foo.txt
.
Вот конфигурация сайта:
server {
listen 443 ssl http2; # when performing http2 example
# listen 443 ssl; # when performing http1 example
server_name h2.test.**********;
root /home/******/h2-test/;
}
Я использую nginx 1.14.2 в Ubuntu 16.04.6 LTS. У вас есть предложения по устранению этой проблемы?
Ниже приводится в основном «теоретический» ответ:
Я полагаю, что вы наблюдаете двойную проблему: характер вашего теста (запрос особенно небольших файлов) и поведение / реализация HTTP / 2 в Chrome.
Если вы посмотрите на свое изображение HTTP / 2, вы увидите, что довольно много (18) запросов завершаются одновременно. Это может сказать вам, что даже если они не запускаются одновременно, они работают параллельно.
Посредством природа мультиплексирования HTTP / 2:
можно даже смешивать части одного сообщения с другим по сети
Таким образом, похоже, что это то, что делает Chrome - видит незавершенный запрос к серверу и пытается параллельно сделать другой запрос через то же мультиплексное соединение.
По какой-то причине у вашего сервера есть своего рода проблема "масштабирования" с параллельными запросами.
Вы сказали, что foo.txt
это небольшой файл, но насколько он маленький?
Там есть http2_chunk_size директива (значение по умолчанию 8k
), что означало бы, что ответ HTTP / 2 разбивается на куски такого размера, и если запросы действительно выполняются параллельно, и foo.txt
меньше чем 8k
, то это приведет к "ожиданию" одного запроса на foo.txt
выполнить еще один запрос на foo.txt
, пока в общей сложности 8k
chunk накапливается для вывода в браузер.
Я бы предложил поиграть с этой директивой и уменьшить ее до меньшего размера, чем запрошенный размер файла, и / или повторить тесты с текстовым файлом, размер которого превышает 8k
.
Наконец, если соединение ненадежно, вы можете столкнуться с проблемой блокировки TCP HOL, которая хуже для HTTP / 2. Цитировать Вот:
Но есть ли сценарии, когда это может ухудшить ситуацию? Да. Причина в том, что приложения, использующие HTTP / 2, могут отправлять гораздо больше запросов по одному TCP-соединению из-за функций конвейерной обработки / мультиплексирования. Неожиданно большие различия в задержке или потеря, влияющая на сегмент в начале линии TCP, повышают вероятность попадания HTTP / 2 в HOLB, и его влияние также больше. По сути, получатель простаивает, пока голова не будет восстановлена, а все последующие сегменты удерживаются стеком TCP. Это означает, что изображение может быть успешно загружено и по-прежнему не отображаться из-за HOLB.