관리자
조회수 307

실험실에서 서버를 벤치마킹한 다음 실제 트래픽에 배포한 후 

벤치마크 성능에 가까운 성과를 달성할 수 없다는 것을 알게 된 적이 있습니까?


 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를 끄거나 매우 짧은 수명으로 제한하라고 말합니다. 이는 SlowHTTPTest 및 Slowloris 서비스 거부 공격에 대한 매우 간단한 벡터를 제공합니다(빠른 해결책은 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 Server(웹 서버)에는 '활성'과 '유휴 keepalive' 상태 사이를 이동할 때 작업자 스레드와 전용 이벤트 스레드 간에 연결을 이동하는 비교적 새로운  이벤트 MPM이 있습니다. 사용하는 다른 모듈이 이 MPM을 지원하는 경우 옵션이 될 수 있습니다. SSL/TLS 연결은 여전히 전용 스레드에서 전적으로 처리된다는 점에 유의하세요.
  • 더 효율적인 처리 모델 사용 - 지금까지 취할 수 있는 가장 간단하고 효과적인 조치는 효율적인 HTTP 프록시를 웹 또는 애플리케이션 서버 앞에 두는 것입니다. NGINX와 같은 이벤트 기반 프록시는 위에서 설명한 동시성 제한이 없습니다. 느린 연결과 유휴 keepalive를 비웃습니다. 게다가 여러 개의 유휴 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를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요.

  


전문가에게 상담받기