현대 시대의 http 연결 유지
따라서 http에 대해 한두 가지를 아는 haproxy 작성자에 따르면 :
Keep-alive는 CPU가 100 배 더 느릴 때 서버의 CPU 사용량을 줄이기 위해 고안되었습니다. 그러나 말하지 않은 것은 영구 연결은 많은 메모리를 소비하지만이를 연 클라이언트를 제외하고는 아무도 사용할 수 없다는 것입니다. 오늘날 2009 년에는 CPU가 매우 저렴하고 메모리는 아키텍처 나 가격에 따라 여전히 몇 기가 바이트로 제한됩니다. 사이트에 연결 유지가 필요한 경우 실제 문제가 있습니다. 로드가 많은 사이트는 최대 동시 클라이언트 수를 지원하기 위해 연결 유지를 비활성화하는 경우가 많습니다. 연결 유지 기능이없는 진짜 단점은 개체를 가져 오는 데 약간의 지연 시간이 늘어난다는 것입니다. 이를 보완하기 위해 브라우저는 비 유지 사이트의 동시 연결 수를 두 배로 늘립니다.
이것은 다른 사람들의 경험과 일치합니까? 즉, 연결 유지없이-결과가 거의 눈에 띄지 않습니까? (아마도 websockets 등을 사용하면 연결이 유지 상태에 관계없이 "열린"상태로 유지된다는 점에 주목할 가치가 있습니다-매우 반응이 빠른 앱의 경우). 서버에서 멀리 떨어져있는 사람들에게 더 큰 효과가 있습니까? 아니면 페이지를로드 할 때 동일한 호스트에서로드 할 아티팩트가 많은 경우입니까? (CSS, 이미지 및 JS와 같은 것이 점점 캐시 친화적 인 CDN에서 나왔다고 생각합니다.)
생각?
(이것은 serverfault.com 일인지 확실하지 않지만 누군가가 저에게 그것을 옮기라고 말할 때까지 게시물을 교차시키지 않을 것입니다).
이 인용문의 저자이기 때문에 응답하겠습니다 :-)
대규모 사이트에는 동시 연결과 대기 시간이라는 두 가지 큰 문제가 있습니다. 동시 연결은 콘텐츠를 다운로드하는 데 오래 걸리는 느린 클라이언트와 유휴 연결 상태로 인해 발생합니다. 이러한 유휴 연결 상태는 연결을 다시 사용하여 연결 유지 (keep-alive)라고하는 여러 개체를 가져 오기 때문에 발생하며 대기 시간으로 인해 더욱 증가합니다. 클라이언트가 서버에 매우 가까우면 연결을 집중적으로 사용하고 거의 유휴 상태가되지 않도록 할 수 있습니다. 그러나 시퀀스가 끝나면 아무도 채널을 빨리 닫는 데 신경 쓰지 않으며 연결은 오랫동안 열려 있고 사용되지 않습니다. 이것이 많은 사람들이 매우 낮은 연결 유지 시간 제한을 사용하도록 제안하는 이유입니다. Apache와 같은 일부 서버에서 설정할 수있는 가장 낮은 시간 제한은 1 초이며 높은로드를 유지하기에는 너무 많은 경우가 많습니다. 당신 앞에 20000 개의 클라이언트가 있고 그들이 평균적으로 매초마다 하나의 개체를 가져 오면 20000 개의 연결이 영구적으로 설정됩니다. Apache와 같은 범용 서버에서 20000 개의 동시 연결은 거대하고로드되는 모듈에 따라 32GB에서 64GB 사이의 RAM이 필요하며 RAM을 추가해도 훨씬 더 높이는 것을 기대할 수 없습니다. 실제로 20000 클라이언트의 경우 브라우저가 가져올 개체가 많은 경우 2 ~ 3 개의 연결을 설정하려고하기 때문에 서버에서 40000 ~ 60000 개의 동시 연결을 볼 수도 있습니다. RAM을 추가해도 훨씬 더 높이 올라가고 싶지 않을 것입니다. 실제로 20000 클라이언트의 경우 브라우저가 가져올 개체가 많은 경우 2 ~ 3 개의 연결을 설정하려고하기 때문에 서버에서 40000 ~ 60000 개의 동시 연결을 볼 수도 있습니다. RAM을 추가해도 훨씬 더 높이 올라가고 싶지 않을 것입니다. 실제로 20000 클라이언트의 경우 브라우저가 가져올 개체가 많은 경우 2 ~ 3 개의 연결을 설정하려고하기 때문에 서버에서 40000 ~ 60000 개의 동시 연결을 볼 수도 있습니다.
각 개체 이후에 연결을 닫으면 동시 연결 수가 크게 감소합니다. 실제로는 개체 사이의 시간에 따라 개체를 다운로드하는 데 걸리는 평균 시간에 해당하는 요소만큼 떨어집니다. 개체 (미니어처 사진, 버튼 등)를 다운로드하는 데 50ms가 필요하고 위와 같이 초당 평균 1 개 개체를 다운로드하면 클라이언트 당 0.05 연결 만 가능합니다. 20000 개의 클라이언트에 대한 동시 연결.
이제 새로운 연결을 설정하는 시간이 중요 할 것입니다. 원거리 클라이언트는 불쾌한 대기 시간을 경험하게됩니다. 과거에 브라우저는 연결 유지가 비활성화되었을 때 많은 양의 동시 연결을 사용했습니다. MSIE에서 4, Netscape에서 8의 숫자를 기억합니다. 이것은 실제로 개체 당 평균 대기 시간을 그만큼 나눈 것입니다. 연결 유지가 모든 곳에 존재하므로 원격 서버에 대한 부하가 더욱 증가하고 브라우저가 인터넷 인프라를 보호하기 때문에 더 이상 그 수가 많지 않습니다.
즉, 오늘날의 브라우저에서는 연결 유지 서비스만큼 응답 성이없는 연결 유지 서비스를 얻는 것이 더 어렵습니다. 또한 일부 브라우저 (예 : Opera)는 휴리스틱을 사용하여 파이프 라이닝을 사용합니다. 파이프 라이닝은 응답을 기다리지 않고 여러 요청을 전송하여 대기 시간을 거의 없애기 때문에 연결 유지를 사용하는 효율적인 방법입니다. 100 장의 작은 사진이있는 페이지에서 시도해 보았습니다. 첫 번째 액세스는 연결 유지가없는 것보다 약 2 배 빠르지 만 다음 액세스는 응답이 너무 작아서 지연 시간 만 계산되기 때문에 약 8 배 빠릅니다. "304"응답).
이상적으로는 브라우저에 몇 가지 튜너 블을 사용하여 가져온 개체 간의 연결을 유지하고 페이지가 완료되면 즉시 삭제해야한다고 말하고 싶습니다. 그러나 불행히도 우리는 그것을 보지 못하고 있습니다.
이러한 이유로 Apache와 같은 범용 서버를 전면에 설치해야하고 많은 양의 클라이언트를 지원해야하는 일부 사이트는 일반적으로 연결 유지를 비활성화해야합니다. 또한 브라우저가 연결 수를 늘리도록 강제하기 위해 다운로드를 병렬화 할 수 있도록 여러 도메인 이름을 사용합니다. 한 번의 추가 왕복이 있으므로 연결 설정이 훨씬 더 높기 때문에 SSL을 집중적으로 사용하는 사이트에서 특히 문제가됩니다.
요즘 더 일반적으로 관찰되는 것은 그러한 사이트가 수만에서 수십만 개의 동시 연결을 처리하는 데 문제가없는 haproxy 또는 nginx와 같은 가벼운 프런트 엔드를 설치하는 것을 선호하고 클라이언트 측에서 연결 유지를 활성화하고 해당 사이트에서 비활성화한다는 것입니다. 아파치 측. 이 측면에서 연결 설정 비용은 CPU 측면에서 거의 null이며 시간 측면에서 전혀 눈에 띄지 않습니다. 이렇게하면 클라이언트 측에서 매우 낮은 시간 초과로 연결 유지로 인한 낮은 대기 시간과 서버 측의 낮은 연결 수라는 두 가지 장점이 모두 제공됩니다. 모든 사람이 행복하다 :-)
일부 상용 제품은 프론트로드 밸런서와 서버 간의 연결을 재사용하고이를 통해 모든 클라이언트 연결을 멀티플렉싱하여이를 더욱 향상시킵니다. 서버가 LB에 가까울 때 이득은 이전 솔루션보다 훨씬 높지 않지만 여러 사용자 간의 예기치 않은 연결 공유로 인해 사용자 간의 세션 교차 위험이 없도록 애플리케이션을 조정해야하는 경우가 많습니다. . 이론적으로 이것은 결코 일어나지 않아야합니다. 현실은 많이 다릅니다 :-)
이것이 쓰여진 후 (그리고 여기에 stackoverflow에 게시 됨) 우리는 이제 인기가 높아지고있는 nginx와 같은 서버를 갖게되었습니다.
예를 들어 nginx는 2.5MB (메가 바이트)의 RAM만으로 단일 프로세스에서 열린 연결 유지 연결 10,000 개를 유지할 수 있습니다. 실제로 매우 적은 RAM으로 수천 개의 연결을 열어 놓는 것이 쉽고, 도달 할 수있는 유일한 제한은 열린 파일 핸들 또는 TCP 연결 수와 같은 다른 제한입니다.
Keep-alive는 keep-alive 사양 자체의 문제가 아니라 Apache의 프로세스 기반 확장 모델과 아키텍처가이를 수용하도록 설계되지 않은 서버에 해킹 된 keep-alive 때문에 문제였습니다.
특히 문제는 Apache Prefork + mod_php + keep-alives입니다. 이것은 모든 단일 연결이 PHP 프로세스가 완전히 유휴 상태이고 연결 유지로만 열려 있어도 PHP 프로세스가 차지하는 모든 RAM을 계속 점유하는 모델입니다. 이것은 확장 가능하지 않습니다. 그러나 서버를 이런 방식으로 설계 할 필요는 없습니다. 서버가 모든 연결 유지 연결을 별도의 프로세스로 유지해야하는 특별한 이유가 없습니다 (특히 모든 프로세스에 완전한 PHP 인터프리터가있는 경우는 해당되지 않음). PHP-FPM과 nginx와 같은 이벤트 기반 서버 처리 모델은 문제를 우아하게 해결합니다.
2015 업데이트 :
SPDY 및 HTTP / 2는 HTTP의 연결 유지 기능을 훨씬 더 나은 것으로 대체합니다. 연결을 유지하고 여러 요청과 응답을 할 수있을뿐만 아니라 다중화 할 수 있으므로 응답을 어떤 순서로든 보낼 수 있습니다. , 그리고 요청 된 순서대로가 아니라 병렬로. 이렇게하면 느린 응답이 더 빠른 응답을 차단하는 것을 방지하고 브라우저가 단일 서버에 대해 여러 개의 병렬 연결을 열어 두려는 유혹을 제거합니다. 이러한 기술은 mod_php 접근 방식의 부적절 성과 PHP-FPM과 같은 것과 별도로 결합 된 이벤트 기반 (또는 최소한 다중 스레드) 웹 서버와 같은 것의 이점을 더욱 강조합니다.
my understanding was that it had little to do with CPU, but the latency in opening of repeated sockets to the other side of the world. even if you have infinite bandwidth, connect latency will slow down the whole process. amplified if your page has dozens of objects. even a persistent connection has a request/response latency but its reduced when you have 2 sockets as on average, one should be streaming data while the other could be blocking. Also, a router is never going to assume a socket connects before letting you write to it. It needs the full round trip handshake. again, i dont claim to be an expert, but this is how i always saw it. what would really be cool is a fully ASYNC protocol (no, not a fully sick protocol).
Very long keep-alives can be useful if you're using an "origin pull" CDN such as CloudFront or CloudFlare. In fact, this can work out to be faster than no CDN, even if you're serving completely dynamic content.
If you have long keep alives such that each PoP basically has a permanent connection to your server, then the first time users visit your site, they can do a fast TCP handshake with their local PoP instead of a slow handshake with you. (Light itself takes around 100ms to go half-way around the world via fiber, and establishing a TCP connection requires three packets to be passed back and forth. SSL requires three round-trips.)
참고URL : https://stackoverflow.com/questions/4139379/http-keep-alive-in-the-modern-age
'programing' 카테고리의 다른 글
밀리 초 지연 값이 큰 경우 setTimeout ()이 "중단"되는 이유는 무엇입니까? (0) | 2020.09.01 |
---|---|
인스턴스 내에서 EC2 태그 쿼리 (0) | 2020.09.01 |
리포지토리 패턴 대 DAL (0) | 2020.09.01 |
Django에서 모든 요청 헤더를 어떻게 얻을 수 있습니까? (0) | 2020.09.01 |
Neo4j-Cypher 대 Gremlin 쿼리 언어 (0) | 2020.09.01 |