Http keep-alive в современном возрасте

Итак, согласно автору haproxy, кто-то знает кое-что о http:

Keep-alive был изобретен для снижения производительности процессора использование на серверах, когда процессоры составляли 100 раза медленнее. Но то, что не сказано, что постоянные соединения потребляют много памяти, хотя они не используются кем угодно, кроме клиента, который открыли их. Сегодня в 2009 году процессоры очень дешево и память по-прежнему ограничена до нескольких гигабайт по архитектуре или цена. Если требуется сайт сохранить жизнь, есть реальная проблема. Часто загружаемые сайты часто отключаются поддерживать максимальный уровень поддержки количество одновременных клиентов. реальный недостаток в том, чтобы не жить немного увеличена латентность до выбор объектов. Браузеры удваивают количество параллельных соединений на сайты, не связанные с хранением, для компенсации это.

(из http://haproxy.1wt.eu/)

Это соответствует опыту других народов? т.е. без сохранения жизни - это результат, который сейчас едва заметен? (его, вероятно, стоит отметить, что с помощью websockets и т.д. соединение поддерживается "открытым", независимо от статуса keep-alive, для приложений с очень отзывчивыми требованиями). Является ли эффект более значительным для людей, удаленных от сервера, или если есть много артефактов для загрузки с одного и того же хоста при загрузке страницы? (Я бы подумал, что такие вещи, как CSS, образы и JS, все чаще поступают из CDN с поддержкой кэширования).

Мысли?

(не уверен, что это вещь serverfault.com, но я не буду переходить по почте, пока кто-то не предложит мне переместить ее там).

Ответ 1

Эй, так как я автор этой цитаты, я отвечу: -)

На больших сайтах есть две большие проблемы: параллельные соединения и латентность. Параллельное подключение вызвано медленными клиентами, которые занимают возраст для загрузки содержимого и состояния незанятых соединений. Эти состояния незанятого соединения вызваны повторным использованием соединения для извлечения нескольких объектов, которые называются keep-alive, что дополнительно увеличивается за счет латентности. Когда клиент находится очень близко к серверу, он может интенсивно использовать соединение и гарантировать, что он почти никогда не работает. Однако, когда последовательность заканчивается, никто не заботится о том, чтобы быстро закрыть канал, и соединение остается открытым и неиспользуемым в течение длительного времени. Это причина, по которой многие люди предлагают использовать очень низкий тайм-аут в режиме ожидания. На некоторых серверах, таких как Apache, самый низкий тайм-аут, который вы можете установить, составляет одну секунду, и часто слишком много для поддержания высоких нагрузок: если у вас есть 20000 клиентов перед вами, и они извлекают в среднем по одному объекту каждую секунду, вы будете эти 20000 подключений установлены постоянно. 20000 одновременных подключений на сервере общего назначения, таком как Apache, огромны, потребуется от 32 до 64 ГБ ОЗУ в зависимости от того, какие модули загружены, и вы, вероятно, не можете надеяться на гораздо большее увеличение даже путем добавления ОЗУ. На практике для 20000 клиентов вы можете видеть даже 40000-60000 одновременных подключений на сервере, потому что браузеры будут пытаться настроить от 2 до 3 соединений, если у них есть много объектов для извлечения.

Если вы закроете соединение после каждого объекта, количество одновременных соединений резко снизится. Действительно, он снизится на коэффициент, соответствующий среднему времени для загрузки объекта на время между объектами. Если вам нужно 50 мс для загрузки объекта (миниатюрная фотография, кнопка и т.д.), И вы загружаете в среднем 1 объект в секунду, как указано выше, тогда у вас будет только 0,05 соединения на каждого клиента, что составляет всего 1000 одновременные подключения для 20000 клиентов.

Теперь настало время установить новые подключения. Удаленные клиенты будут испытывать неприятные задержки. Раньше браузеры использовали большое количество одновременных подключений, когда keep-alive был отключен. Я помню цифры 4 на MSIE и 8 на Netscape. Это действительно разделило бы среднюю задержку на один объект на столько. Теперь, когда keep-alive присутствует повсюду, мы больше не видим таких высоких чисел, потому что это еще больше увеличивает нагрузку на удаленные серверы, а браузеры заботятся о защите интернет-инфраструктуры.

Это означает, что с сегодняшними браузерами сложнее получить услуги, не поддерживающие связь, столь же отзывчивыми, как и поддерживаемые. Кроме того, некоторые браузеры (например, Opera) используют эвристику, чтобы попытаться использовать конвейерную обработку. Конвейеризация - эффективный способ использования keep-alive, поскольку он почти устраняет задержку, отправляя несколько запросов, не дожидаясь ответа. Я попробовал это на странице со 100 маленькими фотографиями, и первый доступ примерно в два раза быстрее, чем без сохранения, но следующий доступ примерно в 8 раз быстрее, потому что ответы настолько малы, что только латентность подсчитывается (только "304" ответов).

Я бы сказал, что в идеале у нас должны быть некоторые настройки в браузерах, чтобы они поддерживали соединения между выбранными объектами и сразу же бросали их, когда страница завершена. Но мы этого не видим.

По этой причине некоторым сайтам, которым необходимо установить серверы общего назначения, такие как Apache на лицевой стороне и которым приходится поддерживать большое количество клиентов, обычно приходится отключать keep-alive. И чтобы заставить браузеры увеличить количество подключений, они используют несколько доменных имен, чтобы загрузки можно было распараллелить. Это особенно проблематично на сайтах, интенсивно использующих SSL, потому что настройка соединения еще выше, поскольку есть еще один раунд.

В настоящее время чаще наблюдается то, что такие сайты предпочитают устанавливать такие легкие интерфейсы, как haproxy или nginx, у которых нет проблем с обработкой от десятков до сотен тысяч одновременных подключений, они позволяют поддерживать работоспособность на стороне клиента и отключать это на стороне Apache. С этой стороны затраты на установление соединения почти нулевые с точки зрения ЦП и не заметны вообще с точки зрения времени. Таким образом, это обеспечивает лучшее из обоих миров: низкая латентность из-за сохранения активности с очень малыми тайм-аутами на стороне клиента и низким количеством подключений на стороне сервера. Все счастливы: -)

Некоторые коммерческие продукты дополнительно улучшают это за счет повторного использования соединений между фронтальным балансиром нагрузки и сервером и мультиплексирования всех клиентских подключений по ним. Когда серверы близки к LB, коэффициент усиления не намного выше, чем предыдущее решение, но часто требуется адаптация к приложению для обеспечения отсутствия риска пересечения сеанса между пользователями из-за неожиданного совместного использования соединения между несколькими пользователями, Теоретически этого никогда не должно быть. Реальность сильно отличается: -)

Ответ 2

За годы, прошедшие с того момента, как это было написано (и опубликовано здесь в stackoverflow), теперь у нас есть серверы, такие как nginx, которые растут в популярности.

nginx, например, может содержать открытые 10 000 поддерживаемых подключений в одном процессе с объемом памяти 2,5 МБ (мегабайт). На самом деле легко провести несколько тысяч подключений с очень небольшой оперативной памятью, и единственными ограничениями, которые вы получите, будут другие ограничения, такие как количество открытых файлов или TCP-соединений.

Keep-alive была проблемой не из-за каких-либо проблем с самой версией keep-alive, а из-за модели масштабирования на основе процессов Apache и удержания-авитов, взломанных на сервер, архитектура которого не была предназначена для размещения он.

Особенно проблематичным является Apache Prefork + mod_php + keep-alives. Это модель, в которой каждое отдельное соединение будет по-прежнему занимать всю оперативную память, которую занимает процесс PHP, даже если он полностью простаивает и остается открытым только как поддерживающий. Это не масштабируемо. Но серверы не должны быть спроектированы таким образом - нет никакой особой причины, по которой серверу необходимо поддерживать каждое поддерживающее соединение в отдельном процессе (особенно если каждый такой процесс имеет полный PHP-интерпретатор). PHP-FPM и модель обработки сервера на основе событий, например, в nginx, устраняют проблему элегантно.

Обновление 2015:

SPDY и HTTP/2 заменяют функциональность HTTP keep-alive еще лучше: возможность не только поддерживать соединение и делать несколько запросов и ответов, но и мультиплексировать их, поэтому ответы могут быть отправлены в любом порядке и параллельно, а не только в том порядке, в котором они были запрошены. Это предотвращает медленные ответы, блокирующие более быстрые, и устраняет соблазн для браузеров держать несколько параллельных подключений к одному серверу. Эти технологии еще больше подчеркивают неадекватность подхода mod_php и преимущества чего-то вроде веб-сервера, основанного на событиях (или, по крайней мере, многопоточности), связанного отдельно с чем-то вроде PHP-FPM.

Ответ 3

я понял, что он имеет мало общего с процессором, но задержка в открытии повторных сокетов на другую сторону мира. даже если у вас есть бесконечная пропускная способность, латентность подключения замедлит весь процесс. если ваша страница имеет десятки объектов. даже постоянное соединение имеет задержку запроса/ответа, но его уменьшает, когда у вас есть 2 сокета в среднем, нужно потоковое передавать данные, а другое может блокироваться. Кроме того, маршрутизатор никогда не собирается предполагать, что сокет соединяется, прежде чем разрешить вам писать на него. Ему необходимо полное рукопожатие в оба конца. опять же, я не претендую на то, чтобы быть экспертом, но так я всегда его видел. что действительно было бы круто - это полностью протокол ASYNC (нет, не полностью больной протокол).

Ответ 4

Очень длинные keep-alives могут быть полезны, если вы используете CDN "origin pull", такой как CloudFront или CloudFlare. Фактически, это может работать быстрее, чем нет CDN, даже если вы используете полностью динамический контент.

Если у вас уже давно есть права, так что каждый PoP в основном имеет постоянное соединение с вашим сервером, то при первом посещении пользователями вашего сайта они могут быстро выполнить рукопожатие TCP с помощью своего локального PoP вместо медленного рукопожатия с вами. (Сам свет занимает около 100 мс, чтобы идти на полпути по всему миру через волокно, а для установления TCP-соединения требуется три пакета для передачи туда и обратно. SSL требует три круглые поездки.)