블로그 | NGINX

HTTP Keepalive 연결 및 웹 성능

NGINX-F5-수평-검정-유형-RGB의 일부
오웬 개렛 썸네일
오웬 개렛
2014년 3월 14일 게시

연구실에서 서버를 벤치마킹한 후 실제 트래픽에 배포해 보았는데, 벤치마크 성능에 근접한 수준까지 달성할 수 없다는 것을 발견한 적이 있습니까? CPU 사용률은 낮고 여유 리소스도 충분한데도 클라이언트들은 응답 시간이 느리다고 불평하고 있으며 서버 사용률을 높이는 방법을 알아낼 수 없습니다.

당신이 관찰하고 있는 것은 우리가 "HTTP 중량 리프팅"이라고 부를 수 있는 효과 중 하나입니다. 이 블로그 게시물에서는 HTTP가 어떻게 작동하는지, 일반적인 HTTP 서버가 HTTP 트랜잭션을 어떻게 처리하는지 살펴보겠습니다. 발생할 수 있는 일부 성능 문제를 살펴보고 NGINX의 이벤트 기반 모델이 어떻게 이러한 HTTP 서버를 위한 매우 효과적인 가속 프록시가 되는지 알아보겠습니다. NGINX를 사용하면 실제 성능을 로컬 벤치마크 수준으로 되돌릴 수 있습니다.

애플리케이션의 속도와 확장성을 개선하기 위한 Linux 및 NGINX 튜닝에 대한 자세한 내용은 블로그의 성능을 위한 NGINX 튜닝을 참조하세요.

HTTP 및 Keepalive 연결 소개

HTTP Keepalive 연결은 지연 시간을 줄이고 웹 페이지 로드 속도를 높여 주는 필수적인 성능 기능입니다.

HTTP는 간단한 텍스트 기반 프로토콜입니다. 이전에 한 적이 없다면 웹 브라우저에 있는 것과 같은 HTTP 디버깅 도구의 출력을 살펴보고 표준 요청 및 응답 구조를 확인하세요.

가장 간단한 구현에서는 HTTP 클라이언트가 대상 서버에 새로운 TCP 연결을 만들고, 요청을 작성하고, 응답을 받습니다. 그러면 서버는 리소스를 해제하기 위해 TCP 연결을 닫습니다.

이러한 작동 모드는 특히 많은 수의 요소가 있는 복잡한 웹 페이지나 네트워크 링크가 느린 경우 매우 비효율적일 수 있습니다. 새로운 TCP 연결을 생성하려면 '3방향 핸드셰이크'가 필요하고, 연결을 끊으려면 2방향 종료 절차도 필요합니다. 각 메시지에 대해 TCP 연결을 반복적으로 만들고 닫는 것은 전화 통화에서 상대방이 말할 때마다 전화를 끊고 다시 전화를 거는 것과 같습니다.

HTTP는 HTTP 트랜잭션이 완료된 후에도 클라이언트와 서버 간의 TCP 연결을 열어두기 위해 keepalive 연결 이라는 메커니즘을 사용합니다. 클라이언트가 다른 HTTP 트랜잭션을 수행해야 하는 경우 새 TCP 연결을 만드는 대신 유휴 Keepalive 연결을 사용할 수 있습니다.

클라이언트는 일반적으로 서버에 여러 개의 TCP 연결을 동시에 열고 모든 연결에서 Keepalive 트랜잭션을 수행합니다. 이러한 연결은 클라이언트나 서버가 더 이상 필요하지 않다고 결정할 때까지(일반적으로 유휴 시간 초과의 결과) 열려 있는 상태로 유지됩니다.

최신 웹 브라우저는 일반적으로 6~8개의 Keepalive 연결을 열어두고 몇 분 동안 유지한 후 시간이 초과됩니다. 웹 서버는 이러한 연결에 시간 초과를 적용하고 더 빨리 닫도록 구성할 수 있습니다.

Keepalives가 HTTP 서버에 미치는 영향은 무엇인가?

많은 클라이언트가 HTTP Keepalive를 사용하고 웹 서버에 동시성 제한이나 확장성 문제가 있는 경우, 해당 제한에 도달하면 성능이 급격히 떨어집니다.

위의 접근 방식은 개별 클라이언트에게 최상의 성과를 제공하도록 설계되었습니다. 불행히도 ' 공유지의 비극 '과 같은 시나리오에서 모든 클라이언트가 이런 방식으로 작동한다면 많은 일반 웹 서버와 웹 애플리케이션의 성능에 부정적인 영향을 미칠 수 있습니다.

그 이유는 많은 서버에 고정된 동시성 제한이 있기 때문입니다. 예를 들어, 일반적인 구성에서 Apache HTTP 서버는 제한된 수의 동시 TCP 연결만 처리할 수 있습니다. 워커 멀티프로세싱 모듈(MPM)을 사용하면 150이고, 프리포크 MPM을 사용하면 256입니다. 각 유휴 HTTP keepalive 연결은 이러한 동시성 슬롯 중 하나를 소모하며, 모든 슬롯이 점유되면 서버는 더 이상 HTTP 연결을 수락할 수 없습니다.

일반적인 통념에 따르면 웹 서버에서 Keepalives를 끄거나 매우 짧은 기간으로 제한하는 것이 좋습니다. 이들은 SlowHTTPTestSlowloris 서비스 거부 공격에 대한 매우 간단한 벡터를 제공합니다(빠른 해결책은 serverfault.com에서 Keep‑Dead 서비스 거부로부터 보호하기 참조).

또한 이러한 웹 및 애플리케이션 서버는 일반적으로 각 연결에 대해 운영 체제 스레드나 프로세스를 할당합니다. TCP 연결은 매우 가벼운 운영 체제 객체이지만, 스레드나 프로세스는 매우 무겁습니다. 스레드와 프로세스에는 메모리가 필요하고 운영 체제에서 적극적으로 관리해야 하며 스레드나 프로세스 간의 '컨텍스트 전환'은 CPU를 소모합니다. 각 연결에 별도의 스레드나 프로세스를 할당하는 것은 매우 비효율적입니다.

동시 클라이언트 연결 수가 많고 각 연결에 스레드나 프로세스를 할당하면 "HTTP 헤비 리프팅"이라는 현상이 발생합니다. 즉, 가벼운 HTTP 트랜잭션을 처리하는 데 비례적으로 큰 노력이 필요합니다.

이것은 실제로 무엇을 의미할까?

현대의 많은 웹 및 애플리케이션 서버에서는 동시성 제한을 소진하는 데 많은 클라이언트가 필요하지 않습니다.

클라이언트가 8개의 TCP 연결을 열고 마지막 사용 후 각각을 15초 동안 활성 상태로 유지하면 클라이언트는 15초 동안 8개의 동시성 슬롯을 소비합니다. 클라이언트가 초당 1명의 비율로 웹사이트에 도착하면 120개의 동시성 슬롯이 지속적으로 유휴 Keepalive 연결에 의해 점유됩니다. 속도가 초당 클라이언트 2명인 경우 240개의 동시성 슬롯이 사용됩니다. 슬롯이 소진되면 기존 연결 시간이 초과될 때까지 새로운 클라이언트는 연결할 수 없습니다.

이로 인해 서비스 수준이 매우 불균형해질 수 있습니다. Keepalive 연결을 성공적으로 확보한 클라이언트는 원하는 대로 서비스를 탐색할 수 있습니다. 동시성 슬롯이 모두 차 있을 때 연결을 시도하는 클라이언트는 잠겨서 대기열에서 기다려야 합니다.

벤치마크 테스트 중에 이러한 효과가 나타나지 않는 이유는 무엇입니까?

이러한 문제는 많은 클라이언트가 있는 느린 네트워크에서만 나타납니다. 빠른 로컬 네트워크를 통해 단일 클라이언트로 벤치마킹할 때는 나타나지 않습니다.

벤치마크에서 이러한 효과를 볼 수 없는 데에는 몇 가지 이유가 있습니다.

  • 벤치마크 중에 keepalives를 활성화하지 않으면 클라이언트는 각 트랜잭션에 대해 새로운 TCP 연결을 생성합니다(그리고 트랜잭션이 완료되면 연결은 해제됩니다). 벤치마크를 빠르고 로컬한 네트워크에서 실행할 가능성이 높으므로 벤치마크가 성공하고 keepalives를 사용하지 않음으로써 발생하는 성능 문제가 나타나지 않습니다.
  • Keepalives를 활성화하는 경우 서버의 제한보다 더 적은 수의 동시 연결을 실행할 수 있으며, 벤치마크 클라이언트가 각 연결을 포화 상태(반복적으로 사용)로 만들어 서버가 최대 용량까지 작동하게 됩니다. 하지만 이는 실제 연결 프로필과 유사하지 않습니다.

대부분의 벤치마크 도구는 성공적인 거래에 대해서만 보고합니다. 리소스 고갈로 인해 중단된 연결은 보고되지 않거나 성공적인 연결의 아주 작은 일부로 나타날 수 있습니다. 이는 실제 교통 문제의 본질을 감춥니다.

이 문제는 얼마나 흔한가요?

모든 스레드 또는 프로세스 기반 웹 또는 애플리케이션 서버는 동시성 제한의 영향을 받기 쉽습니다.

이 문제는 각 연결에 스레드나 프로세스를 할당하는 모든 웹이나 애플리케이션 플랫폼에 본질적으로 발생합니다. 최적화된 벤치마크 환경에서는 감지하기 쉽지 않지만 실제 환경에서는 성능이 저하되고 CPU 사용량이 과도하게 증가하는 것으로 나타납니다.

이 문제를 해결하기 위해 취할 수 있는 몇 가지 조치는 다음과 같습니다.

  • 스레드 또는 프로세스 수를 늘리세요. - 이것은 매우 단기적인 조치입니다. 스레드와 프로세스는 무거운 운영 체제 객체이며, 점점 더 많은 스레드와 프로세스가 생성됨에 따라 관리 오버헤드가 급격히 증가합니다.
  • HTTP keepalives 사용을 비활성화하거나 제한합니다. 이를 통해 동시성 제한은 연기되지만 각 클라이언트의 성능이 크게 저하됩니다.
  • 특수한 keepalive 처리 사용 – Apache HTTP 서버(웹 서버)에는 '활성' 및 '유휴 keepalive' 상태 사이를 이동할 때 작업자 스레드와 전용 이벤트 스레드 간의 연결을 이동하는 비교적 새로운 이벤트 MPM이 있습니다. 다른 모듈에서 이 MPM을 지원하는 경우 이 옵션이 가능할 수 있습니다. SSL/TLS 연결은 여전히 전용 스레드에서 전적으로 처리된다는 점에 유의하세요.
  • 더욱 효율적인 처리 모델 사용 - 지금까지 가장 간단하고 효과적인 방법은 웹 또는 애플리케이션 서버 앞에 효율적인 HTTP 프록시를 배치하는 것입니다. NGINX와 같은 이벤트 기반 프록시는 위에서 설명한 동시성 제한이 없습니다. 느린 연결과 유휴 킵얼라이브는 웃음거리일 뿐입니다. 또한 여러 개의 유휴 Keepalive 연결이 있는 느린 클라이언트 측 연결을 웹 및 애플리케이션 서버에서 최상의 성능을 끌어내는 빠르고 로컬하며 고효율의 벤치마크 스타일 연결로 효과적으로 변환합니다.

NGINX를 가속 HTTP 프록시로 사용

NGINX는 위에서 설명한 동시성 문제가 발생하지 않는 다른 아키텍처를 사용합니다. 느린 클라이언트 연결을 최적화된 벤치마크와 같은 연결로 변환하여 서버에서 최상의 성능을 이끌어냅니다.

NGINX는 매우 효율적인 이벤트 기반 모델을 사용하여 연결을 관리합니다.

각 NGINX 프로세스는 동시에 여러 연결을 처리할 수 있습니다. 새로운 연결이 수락되면 오버헤드가 매우 낮습니다(새로운 파일 설명자와 폴링할 새 이벤트로 구성됨). 위에서 설명한 프로세스별 또는 스레드별 모델과 다릅니다. NGINX는 매우 효과적인 이벤트 루프를 가지고 있습니다:

이를 통해 각 NGINX 프로세스는 동시에 수십, 수천, 수십만 개의 연결로 쉽게 확장할 수 있습니다.

그러면 NGINX는 로컬 Keepalive 연결 풀을 사용하여 요청을 업스트림 서버로 프록시합니다. TCP 연결을 열고 닫는 데 따른 오버헤드가 발생하지 않으며, TCP 스택은 최적의 창 크기와 재시도 매개변수에 빠르게 적응합니다. 로컬의 최적화된 네트워크를 사용하면 쓰기 요청과 읽기 응답이 훨씬 더 빠르게 이루어집니다.

순효과는 업스트림 서버가 빠른 네트워크를 통해 단일 로컬 클라이언트(NGINX)와 통신하게 되고, 이는 불필요하게 연결을 열어두지 않고 연결 설정을 최소화하기 위해 HTTP keepalive 연결을 최적으로 사용하는 클라이언트입니다. 이를 통해 서버는 최적의 벤치마크와 같은 환경으로 돌아갑니다.

NGINX가 HTTP 프록시 역할을 하면 다음과 같은 결과가 나타납니다.

  • 기존 자원의 보다 나은 활용. 더 이상 HTTP에 대한 무거운 작업을 수행하지 않기 때문에 웹 및 애플리케이션 서버는 초당 더 많은 트랜잭션을 처리할 수 있습니다.
  • 오류율 감소 NGINX가 모든 클라이언트에 대한 중앙 스케줄러 역할을 하므로 HTTP 시간 초과가 발생할 가능성이 훨씬 낮습니다.
  • 더 나은 최종 사용자 성능. 서버가 더 효율적으로 실행되고 서비스 연결이 더 빨라집니다.

NGINX가 서비스를 가속화할 수 있는 다른 방법

HTTP의 부담을 덜어주는 것은 NGINX가 과부하된 애플리케이션 인프라에 적용할 수 있는 성능 혁신 조치 중 하나에 불과합니다.

NGINX의 HTTP 캐싱 기능은 표준 캐시 의미론에 따라 업스트림 서버의 응답을 캐싱하여 무엇이 얼마 동안 캐싱되는지 제어합니다. 여러 클라이언트가 동일한 리소스를 요청하는 경우 NGINX는 캐시에서 응답할 수 있고 중복된 요청으로 상위 서버에 부담을 주지 않습니다.

NGINX는 업스트림 서버에서 다른 작업을 오프로드할 수도 있습니다. 대역폭 사용량을 줄이기 위해 데이터 압축 작업을 오프로드하고, SSL/TLS 암호화 및 복호화를 중앙 집중화하고, 초기 클라이언트 인증(예: HTTP 기본 인증 , 외부 인증 서버에 대한 하위 요청 , JSON 웹 토큰 )을 수행하고, 필요한 경우 모든 종류의 규칙을 적용하여 트래픽 속도를 제한할 수 있습니다 .

일반적인 로드 밸런서 또는 ADC가 아닙니다

마지막으로, 다른 가속 프록시, 로드 밸런서, ADC(애플리케이션 전송 컨트롤러)와 달리 NGINX는 완전한 웹 서버 라는 점을 잊지 마세요. NGINX를 사용하면 정적 콘텐츠를 제공하고 , Java, PHP, Python, Ruby 및 기타 언어의 애플리케이션 서버로 트래픽을 전달하고, 미디어(오디오 및 비디오)를 전달하고 , 인증 및 보안 시스템과 통합할 수 있으며, 심지어 NGINX 구성에 내장된 규칙을 사용하여 트랜잭션에 직접 응답할 수도 있습니다.

NGINX와 NGINX Plus는 기본 제공 성능 제한이 없으므로 현재와 미래에 배포하는 하드웨어의 장점을 최대한 활용합니다.

NGINX Plus를 사용해보려면 오늘 무료 30일 체험판을 시작하거나 저희에게 연락해 사용 사례에 대해 논의해 보세요 .


"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."