http keep-живой в современную эпоху


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

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

(от http://haproxy.1wt.eu/)

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

мысли?

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

4 90

4 ответа:

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

есть две большие проблемы на больших сайтах: параллельные соединения и задержки. Одновременное подключение вызвано медленными клиентами, которым требуется время для загрузки содержимого, и состояниями простоя соединения. Эти состояния простоя соединения вызваны повторным использованием соединения для извлечения нескольких объектов, известных как keep-alive, что еще больше увеличивается с задержкой. Когда клиент находится очень близко к серверу, он может сделать интенсивное использование соединения и обеспечение его почти никогда не простаивает. Однако, когда последовательность заканчивается, никто не заботится о том, чтобы быстро закрыть канал и соединение остается открытым и не используется в течение длительного времени. Вот почему многие люди предлагают использовать очень низкий тайм-аут 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 присутствует везде, мы больше не видим таких высоких цифр, потому что это еще больше увеличивается нагрузка на удаленные серверы, а также браузеры заботятся о защите инфраструктуры интернета.

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

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

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

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

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

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

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

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

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

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

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

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

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

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