블로그 | NGINX

MRA, 6부: NGINX Plus로 Circuit Breaker 패턴 구현

NGINX-F5-수평-검정-유형-RGB의 일부
크리스 스테트슨 썸네일
크리스 스테트슨
2016년 11월 10일 게시

작성자 메모이 블로그 게시물은 시리즈 중 여섯 번째입니다.

  1. NGINX의 마이크로서비스 참조 아키텍처 소개
  2. MRA, 2부: 프록시 모델
  3. MRA, 3부: 라우터 메시 모델
  4. MRA, 4부: 패브릭 모델
  5. MRA, 5부: 마이크로서비스를 위한 12가지 요소 앱 적용
  6. MRA, 6부: NGINX Plus를 사용하여 Circuit Breaker 패턴 구현(이 게시물)

여섯 개의 블로그와 마이크로서비스 애플리케이션을 위한 웹 프런트엔드에 대한 블로그<.htmla>가 무료 전자책 으로 엮어졌습니다 .

마이크로서비스에 대한 다른 NGINX 리소스도 확인해 보세요.

 

마이크로서비스 애플리케이션 설계는 애플리케이션의 기능에 있어서 대대적인 변화를 가져왔습니다. 마이크로서비스 아키텍처에서 "애플리케이션"은 이제 작업을 수행하고 기능을 제공하기 위해 서로 의존하는 서비스 모음입니다. 복잡한 애플리케이션에서는 서비스 그래프가 매우 깊어질 수 있으며 다양한 서비스 간에 여러 가지 상호 종속성이 있을 수 있습니다.

예를 들어, 사용자 서비스는 해당 서비스가 제공하는 데이터에 의존하는 다른 여러 서비스에 필수적일 수 있습니다. 이런 시나리오에서 사용자 서비스에 장애가 발생하면 애플리케이션 전체에 걸쳐 장애가 연쇄적으로 발생할 수 있습니다.

Circuit Breaker 패턴은 Martin Fowler가 유명하게 만든 용어로, 마이크로서비스 아키텍트들 사이에서 연쇄 서비스 실패를 방지하기 위한 애플리케이션 설계 패턴으로 널리 사용되고 있습니다. Circuit Breaker 패턴의 아이디어는 장애를 방지하기 위해 애플리케이션 서비스와 그 사이를 흐르는 트래픽을 모니터링하고, 장애가 발생하면 애플리케이션에 미치는 장애의 영향을 최소화하는 것입니다.

마이크로서비스의 경우, 회로 차단기 패턴은 하향식 복원력을 제공하므로 특히 가치가 있습니다. 올바르게 구현하면 서비스를 사용할 수 없을 때에도 서비스 연속성을 제공함으로써 연쇄적 실패를 방지하는 데 도움이 될 수 있습니다. 서킷 브레이커 패턴은 넷플릭스가 애플리케이션 설계 철학의 핵심 구성 요소로 가장 유명하게 채택했습니다 .

실패를 피하지 말고, 받아들이세요

현대 애플리케이션 설계의 핵심 원칙은 실패가 발생할 것이라는 것입니다. 현대적 애플리케이션이 의존하는 계층적 케이크(클라우드 호스팅 가상 머신부터 컨테이너, 애플리케이션 라이브러리, 동적 네트워킹까지)는 모든 애플리케이션에 움직이는 부품이 매우 많다는 것을 의미합니다. 어느 시점에서 애플리케이션의 하나 이상의 부분이 어떤 방식으로든 실패할 것이라고 가정해야 합니다. 실패를 예상하고 실패의 영향을 완화하는 메커니즘을 구축하면 애플리케이션의 복원력을 크게 높이는 데 도움이 됩니다.

회로 차단기 패턴의 가장 중요한 목표 중 하나는 무엇보다도 고장을 방지하는 것입니다. 메모리 부족과 같은 일부 오류 조건의 경우 오류가 곧 발생할 것이라는 것을 인식하고 이를 방지하기 위한 조치를 취할 수 있습니다. 일반적으로 이는 서비스에서 상태가 좋지 않다는 신호를 보내고, 회로 차단기가 요청 수를 조절하거나 요청을 완전히 다시 라우팅하여 서비스가 복구할 수 있는 기회를 제공함으로써 수행됩니다. 서비스가 복구되면 회로 차단기가 서비스에 대한 요청을 천천히 늘리는 것이 좋습니다. 이렇게 하면 서비스가 즉시 과부하 상태가 되어 다시 건강에 해로울 위험이 없습니다.

NGINX 마이크로서비스 참조 아키텍처 에는 resizer 라는 서비스가 있습니다. 큰 사진을 시스템에 업로드하면 크기 조절기가 사진을 압축 해제하고 회전을 보정한 후 크기를 줄이고 다시 줄여서 보정된 원본 이미지와 크기가 조절된 두 개의 이미지를 개체 저장소에 저장합니다. 이러한 프로세스의 특성상 크기 조절은 애플리케이션에서 프로세서와 메모리를 가장 많이 사용하는 부분이 됩니다.

동시에 많은 이미지의 크기를 조정할 경우, 크기 조정 프로그램의 메모리가 소진되고, 어떤 경우에는 완전히 실패할 수도 있습니다. 문제를 방지하기 위해, 리사이저 서비스와 이미지를 공급 하는 업로더 서비스 인스턴스 사이에 회로 차단기를 두었습니다. 업로더는 리사이저 인스턴스의 상태를 정기적으로 쿼리합니다. 쿼리는 리사이저가 사용 가능한 메모리의 80% 이상을 사용했는지 평가하고 기타 상태 검사를 수행하도록 하며 업로더에게 상태 정보를 응답합니다.

리사이저 인스턴스가 비정상임을 나타내는 경우 업로더는 그림 1에서 볼 수 있듯이 요청을 다른 인스턴스로 라우팅하지만 해당 리사이저 인스턴스가 복구되었는지 계속 확인합니다. 리사이저 인스턴스가 다시 정상 상태임을 나타내면 로드 밸런싱된 풀로 다시 들어가고 업로더는 트래픽을 인스턴스의 전체 용량까지 천천히 늘립니다. 이러한 설계는 크기 조정 인스턴스가 완전히 실패하는 것을 방지하고, 작업이 시작되지만 완료되지 않는 것을 방지하고, 프로세스가 실패했을 사용자가 과도하게 기다리는 것을 방지하며, 시스템이 전송된 요청 스트림을 가장 효과적으로 처리하는 데 도움이 됩니다.

회로 차단기 패턴은 건강에 해로운 인스턴스로의 트래픽을 차단합니다. 회로 차단기와 NGINX는 잘 작동합니다.
그림 1. 활성 상태 검사는 건강에 해로운 마이크로서비스 인스턴스에 대한 호출을 방지합니다.

회로 차단기 패턴은 일관성을 향상시킵니다.

NGINX 수준에서 회로 차단기를 구현하는 이점 중 하나는 마이크로서비스 애플리케이션 전반에서 회로 차단기를 관리하기 위한 보편적이고 일관적이며 매우 유연한 계층을 생성한다는 것입니다. 이러한 보편성과 일관성은 각 언어의 회로 차단기 라이브러리의 미묘한 차이와 불일치를 관리하고 이를 중심으로 구축할 필요가 없다는 것을 의미합니다.

각 서비스의 코드에서 대부분의 회로 차단기 기능을 유지하고 대신 NGINX Plus에서 구현하면 많은 이점을 얻을 수 있습니다.

  • 예를 들어 Java로 작성된 서비스의 회로 차단기는 PHP로 작성된 서비스의 회로 차단기와 동일하며 회로 차단기 자체는 필요에 따라 다른 언어로 작성될 수 있습니다.
  • 각 서비스에서 사용하는 다양한 언어와 지원 라이브러리에서 회로 차단기 기능을 다시 구현할 필요가 없습니다.
  • 회로 차단기 코드를 포함할 필요가 없는 각 서비스는 간소화되어 더 빠르게 실행되고 작성, 디버깅, 실행 및 유지 관리가 더 쉬워집니다.
  • 각 서비스에 대한 지원 코드가 간소화되어 사용되는 라이브러리와 시스템의 조합은 서비스의 핵심 기능만을 반영할 수 있습니다.
  • 회로 차단기 코드가 간소화되었습니다. 한 곳에만 존재하므로 로컬 컨텍스트에 맞게 조정할 필요 없이 필수 요소로 축소할 수 있습니다.
  • 회로 차단기 코드는 캐싱과 같은 NGINX Plus 기능을 활용하여 훨씬 더 강력해질 수 있습니다.
  • NGINX Plus 레벨 회로 차단기 코드를 미세 조정한 다음 온프레미스, 다양한 클라우드 플랫폼, 혼합 환경 등 다른 애플리케이션과 배포 플랫폼에서 재사용할 수 있습니다.

하지만 NGINX Plus만으로는 회로 차단기를 구현할 수 없다는 점에 유의하는 것이 중요합니다. 진정한 회로 차단기를 사용하려면 서비스가 지정된 URI(일반적으로 /health )에서 내성적이고 적극적인 상태 검사를 제공해야 합니다. 건강 검진은 해당 서비스의 요구 사항에 적합해야 합니다.

상태 점검을 개발할 때는 서비스 실패 프로필과 데이터베이스 연결 실패, 메모리 부족, 디스크 공간 부족, CPU 과부하 등 실패를 일으킬 수 있는 조건의 종류를 이해해야 합니다. 이러한 상태는 상태 검진 과정에서 평가되어 건강 또는 건강하지 않음의 이진 상태가 제공됩니다.

회로 차단기 패턴은 유연성을 제공합니다

여기에 설명된 대로 NGINX 수준에서 회로 차단기 패턴을 구현하는 경우 서비스 인스턴스가 비정상적이라는 것을 통신할 때 상황을 처리하는 것은 NGINX Plus의 몫입니다. 다양한 옵션이 있습니다.

첫 번째 옵션은 요청을 다른 정상적인 인스턴스로 리디렉션하고, 비정상적인 인스턴스에 대한 쿼리를 계속하여 복구되는지 확인하는 것입니다. 두 번째 옵션은 서비스를 요청하는 클라이언트에게 캐시된 응답을 제공하여 서비스를 사용할 수 없는 경우에도 안정성을 유지하는 것입니다. 이 솔루션은 콘텐츠 서비스와 같은 읽기 지향 서비스와 잘 작동합니다.

또 다른 옵션은 대체 데이터 소스를 제공하는 것입니다. 예를 들어, 당사 고객 중 한 명은 프로필 데이터를 사용하여 사용자에게 타겟 광고를 제공하는 개인화된 광고 서버를 보유하고 있습니다. 개인화된 광고 서버가 다운되면 사용자 요청은 모든 사람에게 적합한 일반적인 광고 세트를 제공하는 백업 서버로 리디렉션됩니다. 이러한 대체 데이터 소스 접근 방식은 매우 강력할 수 있습니다.

마지막으로, 서비스 실패 프로필을 명확하게 이해하고 있다면 회로 차단기에 속도 제한을 추가하여 실패를 완화할 수 있습니다. 요청은 서비스가 처리할 수 있는 속도에 따라서만 허용됩니다. 이렇게 하면 회로 차단기 내부에 버퍼가 생성되어 트래픽 급증을 흡수할 수 있습니다.

속도 제한은 라우터 메시 모델 과 같은 중앙 집중형 부하 분산 시나리오에서 특히 강력할 수 있습니다. 여기서 애플리케이션 트래픽은 사이트 전체의 총 트래픽 사용량을 잘 이해할 수 있는 제한된 수의 부하 분산 장치를 통해 라우팅됩니다.

NGINX Plus에서 Circuit Breaker 패턴 구현

위에서 설명한 대로, 회로 차단기 패턴은 건강에 해로운 서비스로 가는 트래픽을 줄이거나 해당 서비스에서 요청을 라우팅하여 장애가 발생하기 전에 이를 방지할 수 있습니다. 이를 위해서는 각 서비스의 내부 상태 모니터에 연결된 활성 상태 검사가 필요합니다. 불행히도 수동적 상태 점검은 실패 여부만 점검하기 때문에 효과가 없습니다. 실패가 발생한 후에는 예방 조치를 취하기에는 너무 늦습니다. 이러한 이유로 NGINX 오픈 소스는 회로 차단기 패턴을 구현할 수 없습니다. 수동 상태 검사만 지원합니다.

그러나 NGINX Plus는 상태 문제를 확인하고 대응하기 위한 다양한 옵션을 갖춘 강력한 활성 상태 점검 시스템을 갖추고 있습니다. 마이크로서비스 참조 아키텍처의 일부 서비스 유형에 대한 구현을 살펴보면 회로 차단기 구현을 위한 옵션과 사용 사례에 대한 좋은 예를 알 수 있습니다.

리사이저에 연결되는 업로더 서비스부터 시작해 보겠습니다. 업로더는 이미지를 객체 저장소에 넣은 다음 리사이저에게 이미지를 열고 수정하고 크기를 조절하라고 지시합니다. 이는 컴퓨팅 및 메모리 집약적인 작업입니다. 업로더는 리사이저의 상태를 모니터링하고 리사이저에 과부하가 걸리지 않도록 해야 합니다. 리사이저는 말 그대로 실행 중인 호스트를 죽일 수 있기 때문입니다.

가장 먼저 해야 할 일은 크기 조절 상태 확인을 위한 위치 블록을 만드는 것입니다. 이 블록은 내부 위치이므로 서버의 표준 URL( http://example.com/health-check-resizer )에 대한 요청으로 액세스할 수 없습니다. 대신, 이는 상태 점검 정보의 플레이스홀더 역할을 합니다. health_check 지시어는 3초마다 /health URI로 상태 검사를 보내고 match 블록에 정의된 conditions 이라는 테스트를 사용하여 서비스 인스턴스의 상태를 검사합니다. 서비스 인스턴스는 단일 검사를 놓치면 비정상으로 표시됩니다. proxy_* 지시어는 HTTP 1.1을 통한 TLS 1.2를 사용하여 지정된 HTTP 헤더를 null로 설정하여 리사이저 업스트림 그룹에 상태 검사를 보냅니다.

위치 /health-check-resizer { 내부;
health_check uri=/health match=conditions 실패=1 간격=3초;

proxy_pass https://resizer;
proxy_ssl_session_reuse 켜짐;
proxy_ssl_protocols TLSv1.2;
proxy_http_version 1.1;
proxy_set_header 연결 "";
proxy_set_header 수락 인코딩 "";
}

다음 단계는 건강한 조건과 건강에 해로운 조건을 나타내는 응답을 지정하기 위해 조건 일치 블록을 만드는 것입니다. 첫 번째 검사는 응답 상태 코드입니다. 범위 내에 있는지 확인하십시오.200 ~을 통해399 , 테스트는 다음 평가 문장으로 진행됩니다. 두 번째 확인 사항은 Content-Typeapplication/json 인지 확인하는 것입니다. 마지막으로 세 번째 검사는 deadlocks , Disk , Memory 메트릭 값에 대한 정규 표현식 일치입니다. 모든 항목이 건강한 경우 해당 서비스는 건강한 것으로 판단합니다.

일치 조건 { 상태 200-399;
헤더 콘텐츠 유형 ~ "application/json";
본문 ~ '{
"deadlocks":{"healthy":true},
"Disk":{"healthy":true},
"Memory":{"healthy":true}
}';
}

NGINX Plus 회로 차단기/상태 확인 시스템에도 느린 시작 기능이 있습니다. 업스트림 블록의 리사이저 서비스에 대한 서버 지시문에 대한 slow_start 매개변수는 리사이저 인스턴스가 비정상 상태에서 처음 반환될 때 트래픽 흐름을 조절하도록 NGINX Plus에 지시합니다. 정상적인 서비스에 동일한 수의 요청을 보내는 대신, 복구 중인 서비스에 대한 트래픽은 slow_start 매개변수에서 지정한 기간(이 경우 30초) 동안 천천히 정상 속도로 증가합니다. 느린 시작은 서비스가 완전한 성능으로 돌아올 가능성을 높이는 동시에 그렇지 않을 경우의 영향을 줄여줍니다.

업스트림 리사이저 { 서버 리사이저 slow_start=30s;
존 백엔드 64k;
least_time last_byte;
keepalive 300;
}

요청 제한은 서비스에 대한 요청 흐름을 관리하고 조절합니다. 특정 시점에 처리할 수 있는 요청 수를 알 만큼 애플리케이션의 실패 프로필을 잘 이해한다면, 요청 제한을 구현하는 것이 프로세스에 큰 도움이 될 수 있습니다. 하지만 이 기능은 NGINX Plus가 서비스로 전달되는 총 연결 수를 완전히 인식하고 있는 경우에만 작동합니다. 이러한 이유로 Fabric 모델에서와 같이 서비스 자체가 있는 컨테이너에서 실행되는 NGINX Plus 인스턴스에서 요청 제한 회로 차단기를 구현하거나 클러스터의 모든 트래픽을 관리하는 중앙 집중식 로드 밸런서에서 구현하는 것이 가장 유용합니다.

다음 구성 코드 조각은 컨테이너의 크기 조정 서비스 인스턴스에 적용되는 요청에 대한 속도 제한을 정의합니다. limit_req_zone 지시어는 초당 100개의 요청으로 속도 제한을 정의합니다. $server_addr 변수는 키로 사용되며, 이는 크기 조정 컨테이너에 대한 모든 요청이 제한에 포함된다는 것을 의미합니다. 해당 영역의 이름은 moderateReqs 이고 요청 수를 유지하는 시간 프레임은 1분입니다. limit_req 지시어를 사용하면 NGINX Plus가 최대 150개의 요청을 버퍼링할 수 있습니다. 해당 숫자를 초과하면 클라이언트는 다음을 수신합니다.503 limit_req_status 지시문에서 지정한 오류 코드는 서비스를 사용할 수 없음을 나타냅니다.

http { # 중재된 배달
limit_req_zone $server_addr zone=moderateReqs:1m rate=100r/s;
# ...
server {
# ...
limit_req zone=moderateReqs burst=150;
limit_req_status 503;
# ...
}
}

NGINX Plus에서 서킷 브레이커를 실행하는 또 다른 강력한 이점은 캐싱 기능을 통합하고 캐시된 데이터를 중앙에서 유지 관리하여 시스템 전체에서 사용할 수 있다는 것입니다. 이 기능은 백엔드에서 읽는 데이터가 자주 변경되지 않는 콘텐츠 서버와 같은 읽기 지향 서비스에 특히 유용합니다.

proxy_cache_path /app/cache 레벨=1:2 키_존=oauth_cache:10m 최대_크기=10m 비활성=15초 use_temp_path=off;
업스트림 사용자 관리자 {
서버 사용자 관리자;
존 백엔드 64k;
least_time last_byte;
keepalive 300;
}

서버 {
listen 443 ssl;
위치 /v1/users {
proxy_pass http://user-manager;
proxy_cache oauth_cache;
proxy_cache_valid 200 30초;
proxy_cache_use_stale 오류 시간 초과 invalid_header 업데이트
http_500 http_502 http_503 http_504;
}
}

그림 2에서 볼 수 있듯이 데이터 캐싱은 많은 고객 데이터 요청이 마이크로서비스 인스턴스에 도달하지 못한다는 것을 의미하며, 이전에 수신되지 않았던 요청을 위한 용량이 확보됩니다.

NGINX Plus는 마이크로서비스 회로 차단기 역할을 하며 캐싱도 지원합니다.
그림 2. 캐싱은 일반적으로 마이크로서비스 인스턴스에 대한 호출을 방지하여 성능을 높이는 데 사용되지만 완전한 서비스 실패 시 서비스의 연속성을 제공하는 역할도 합니다.

그러나 데이터가 변경될 수 있는 서비스, 예를 들어 사용자 관리자 서비스의 경우 캐시를 신중하게 관리해야 합니다. 그렇지 않으면 사용자가 프로필을 변경했지만 데이터가 캐시되어 일부 상황에서는 이전 데이터가 표시되는 상황이 발생할 수 있습니다. 합리적인 시간 초과와 최종 일관성을 갖춘 고가용성 원칙을 수용하면 이 난제를 해결할 수 있습니다.

NGINX 캐시의 훌륭한 기능 중 하나는 서비스가 완전히 사용할 수 없더라도 캐시된 데이터를 계속 제공할 수 있다는 것입니다. 위의 스니펫에서 서비스가 가장 일반적인 네 가지 중 하나로 응답하는 경우입니다.500 ‑시리즈 오류 코드.

캐싱은 서버가 다운된 경우에도 클라이언트에 응답할 수 있는 유일한 옵션은 아닙니다. 회로 차단기 패턴은 유연성을 제공합니다 에서 언급했듯이, 저희 고객 중 한 명은 개인화된 광고 서버가 다운될 경우를 대비해 복원력이 뛰어난 솔루션이 필요했으며, 캐시된 응답은 좋은 솔루션이 아니었습니다. 그 대신 그들은 개인화된 서버가 다시 온라인 상태가 될 때까지 일반적인 광고를 제공하는 일반 광고 서버를 원했습니다. 이는 서버 지시문에 backup 매개변수를 사용하면 쉽게 달성할 수 있습니다. 다음 스니펫은 personal-ad-server 도메인에 정의된 모든 서버를 사용할 수 없는 경우 generic-ad-server 도메인에 정의된 서버가 대신 사용되도록 지정합니다.

업스트림 개인 광고 서버 { 서버 개인 광고 서버;
서버 일반 광고 서버 백업;
존 백엔드 64k;
최소_시간 마지막_바이트;
keepalive 300;
}

마지막으로, NGINX가 서비스의 응답 코드를 평가 하고 개별적으로 처리하는 것이 가능합니다. 다음 스니펫에서 서비스가 다음을 반환하는 경우503 오류가 발생하면 NGINX Plus는 해당 요청을 대체 서비스로 전송합니다. 예를 들어, 크기 조절기에 이 기능이 있고 로컬 인스턴스가 과부하되거나 작동이 중단되면 요청은 크기 조절기의 다른 인스턴스로 전송됩니다.

위치 / { 오류 페이지 503 = @fallback;
}

위치 @fallback {
프록시 패스 http://alternative-backend;
}

결론

회로 차단기 패턴은 마이크로서비스 애플리케이션에 회복성과 제어력을 제공하는 강력한 도구입니다. NGINX Plus는 사용자 환경에 회로 차단기를 구현하기 위한 많은 기능과 옵션을 제공합니다. 회로 차단기 패턴을 구현하는 핵심은 보호하려는 서비스의 장애 프로필을 이해한 다음, 가능한 경우 장애를 가장 잘 방지하고 장애가 발생했을 때 장애의 영향을 가장 잘 완화할 수 있는 옵션을 선택하는 것입니다.

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


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