작성자 메모 – 이 블로그 게시물은 시리즈 중 여섯 번째입니다.
- NGINX의 마이크로서비스 참조 아키텍처 소개
- MRA, 2부: 프록시 모델
- MRA, 3부: 라우터 메시 모델
- MRA, 4부: 패브릭 모델
- MRA, 5부: 마이크로서비스를 위한 12가지 요소 앱 적용
- MRA, 6부: NGINX Plus로 Circuit Breaker 패턴 구현(이 게시물)
6개의 블로그 모두와 마이크로서비스 애플리케이션을 위한 웹 프런트엔드에 대한 블로그 <.htmla>가 무료 전자책 으로 엮어졌습니다 .
마이크로서비스에 대한 다른 NGINX 리소스도 확인해 보세요.
- Chris Richardson이 쓴 마이크로서비스 애플리케이션 설계 에 관한 매우 유용하고 인기 있는 시리즈
- NGINX 및 NGINX Plus를 사용하여 마이크로서비스를 구현하는 방법에 대한 추가 팁이 포함된 무료 전자책으로 수집된 Chris Richardson 기사
- 기타 마이크로서비스 블로그 게시물
- 마이크로서비스 웨비나
마이크로서비스 애플리케이션 설계는 애플리케이션의 기능 방식에 큰 변화를 가져왔습니다.
마이크로서비스 아키텍처에서 "애플리케이션"은 작업을 수행하고 기능을 제공하기 위해
서로 의존하는 서비스들의 모음으로 정의됩니다.
복잡한 애플리케이션에서는 서비스 간의 의존 관계가 매우 복잡할 수 있으며,
사용자 서비스와 같이 다른 많은 서비스에 필수적인 데이터 제공 서비스의 실패는
전체 애플리케이션에 연쇄적인 장애를 초래할 가능성이 있습니다.
이를 해결하기 위한 패턴 중 하나가 바로 Circuit Breaker 패턴입니다.
이 패턴은 Martin Fowler에 의해 널리 알려졌으며,
마이크로서비스 환경에서 연쇄적인 서비스 장애를 예방하는 데 중요한 설계 방식으로 인정받고 있습니다.
Circuit Breaker 패턴은 서비스와 그 사이를 흐르는 트래픽을 모니터링하여 장애를 방지하고,
문제가 발생했을 때 영향 범위를 최소화합니다.
특히 마이크로서비스 아키텍처에서는 서비스의 연속성을 유지하면서 연쇄 장애를 방지하는 데 효과적이며,
Netflix와 같은 기업이 이를 성공적으로 채택하여 널리 알려지게 되었습니다.
현대 애플리케이션 설계의 핵심은 실패를 피하려고 하기보다는
실패가 발생할 것을 전제로 복원력을 강화하는 데 있습니다.
애플리케이션의 다양한 구성 요소와 계층 구조는 어느 한 부분에서라도 장애가 발생할 가능성을 항상 내포하고 있습니다.
따라서 실패를 예상하고, 그 영향을 완화하는 메커니즘을 구축하는 것이 애플리케이션 복원력을 높이는 데 필수적입니다.
Circuit Breaker 패턴은 우선적으로 장애를 방지하고자 합니다.
예를 들어, 서비스가 비정상 상태에 도달할 조짐을 보이면 경고 신호를 보내거나
요청을 제한하여 서비스가 복구할 시간을 확보합니다.
이후 서비스가 정상 상태로 돌아오면 요청을 점진적으로 늘려,
즉각적인 과부하로 인해 다시 장애가 발생하지 않도록 합니다.
NGINX 마이크로서비스 참조 아키텍처의 Resizer 서비스 사례를 보면,
대량의 이미지 크기 조정 작업으로 인해 메모리 부족 문제가 발생할 수 있습니다.
이를 방지하기 위해 업로더와 Resizer 서비스 사이에 Circuit Breaker를 도입했습니다.
업로더는 주기적으로 Resizer의 상태를 확인하여 메모리 사용량이 임계치를 초과할 경우
요청을 다른 인스턴스로 전환하고, 문제가 해결되면 다시 로드 밸런싱 풀에 추가합니다.
이러한 설계를 통해 장애를 예방하고, 사용자 경험을 보호하며, 시스템의 안정성을 유지할 수 있습니다.
그림 1. 활성 상태 검사는 건강에 해로운 마이크로서비스 인스턴스에 대한 호출을 방지합니다.
회로 차단기 패턴은 일관성을 향상시킵니다
NGINX에서 회로 차단기를 구현하면 마이크로서비스 애플리케이션 전반에 걸쳐
일관적이고 유연한 관리 계층을 제공할 수 있습니다.
이는 개별 언어별 회로 차단기 라이브러리에서 발생할 수 있는 뉘앙스나 불일치를 직접 처리할 필요를 없애줍니다.
특히 NGINX Plus를 활용하여 각 서비스의 코드에서 회로 차단기 기능을 제거하고 중앙에서 관리하면
다음과 같은 이점을 얻을 수 있습니다:
- 언어와 독립적인 통합:
Java로 작성된 서비스의 회로 차단기는 PHP로 작성된 서비스와 동일하게 작동합니다.
이는 회로 차단기가 특정 언어에 국한되지 않고 다양한 언어에서도 유연하게 활용 가능함을 의미합니다. - 재구현 불필요:
각 서비스에서 별도로 회로 차단기 기능을 구현할 필요가 없어 언어 별로 라이브러리를 다시 작성하거나 유지 관리할 부담이 줄어듭니다. - 간소화된 코드:
각 서비스는 회로 차단기 관련 코드를 포함하지 않음으로써 더 단순해지고 실행 속도가 빨라지며 작성, 디버깅, 유지 관리가 쉬워집니다. - 서비스 중심 최적화:
서비스 지원 코드는 서비스의 핵심 기능만을 반영하며, 사용되는 라이브러리나 시스템 구성 요소도 단순화됩니다. - 중앙화된 관리:
회로 차단기 코드는 한 곳에서 관리되며, 지역적 상황에 맞춘 조정 없이 필수적인 기능만으로 축소됩니다. - 고도화된 기능 활용:
NGINX Plus의 기능(예: 캐싱)을 활용하여 더욱 강력한 회로 차단기를 구현할 수 있습니다. - 재사용성:
NGINX Plus에서 최적화된 회로 차단기 코드는 온프레미스, 클라우드, 하이브리드 환경 등 다양한 배포 플랫폼에서 재사용할 수 있습니다.
다만, 진정한 회로 차단기는 NGINX Plus만으로 구현할 수는 없습니다.
회로 차단기를 제대로 활용하려면 서비스에서 특정 URI(일반적으로 /health)를 통해 상태 검사를 제공해야 합니다.
상태 검사는 서비스의 특성에 맞게 설계되어야 하며, 이를 통해 장애를 사전에 파악하고 대응할 수 있습니다.
상태 점검 개발 시 고려 사항
상태 점검을 설계할 때는 서비스의 실패 패턴과 장애를 유발할 수 있는 조건
(예: 데이터베이스 연결 실패, 메모리 부족, 디스크 공간 부족, CPU 과부하 등)을 면밀히 이해해야 합니다.
이러한 조건은 상태 점검 프로세스에서 평가되며, 그 결과로 서비스의 정상 또는 비정상 상태를 결정합니다.
회로 차단기 패턴은 유연성을 제공합니다
여기에서 설명한 것처럼, NGINX 레벨에서 회로 차단기 패턴을 구현하면
서비스 인스턴스가 비정상 상태라고 통신할 때 해당 상황을 처리하는 것은 NGINX Plus의 역할입니다.
이를 위해 제공되는 여러 옵션이 있습니다.
요청 리디렉션:
요청을 다른 건강한 인스턴스로 리디렉션하고, 동시에 건강하지 않은 인스턴스에 대한 쿼리를 계속 수행하여 복구 여부를 확인합니다.
캐시된 응답 제공:
서비스를 요청하는 클라이언트에 캐시된 응답을 제공하여 서비스가 비정상적이더라도 안정성을 유지합니다.
이 방법은 콘텐츠 서비스와 같은 읽기 중심 서비스에 적합합니다.
대체 데이터 소스 제공:
예를 들어, 프로필 데이터를 활용해 타겟팅 광고를 제공하는 개인화된 광고 서버가 다운될 경우,
모든 사용자에게 적합한 일반적인 광고를 제공하는 백업 서버로 요청을 리디렉션할 수 있습니다.
이 대체 데이터 소스 방식은 매우 강력한 솔루션이 될 수 있습니다.
속도 제한:
서비스의 실패 프로필을 명확히 이해했다면, 회로 차단기에 속도 제한을 추가하여
요청이 처리 가능한 속도로만 허용되도록 설정할 수 있습니다.
이를 통해 회로 차단기 내에 트래픽 급증을 흡수할 수 있는 버퍼를 생성할 수 있습니다.
속도 제한은 라우터 메시 모델과 같은 중앙 집중형 부하 분산 시나리오에서 특히 효과적입니다.
이 모델에서는 사이트의 총 트래픽 사용량을 잘 파악할 수 있는
소수의 부하 분산 장치를 통해 애플리케이션 트래픽이 라우팅됩니다.
NGINX Plus에서 회로 차단기 패턴 구현
앞서 설명한 대로, 회로 차단기 패턴은
비정상적인 서비스로 향하는 트래픽을 줄이거나 이를 회피함으로써
장애를 미연에 방지할 수 있습니다.
이를 위해서는 각 서비스에 내장된 활성 건강 검사와 연결된 상태 모니터링이 필요합니다.
수동 건강 검사는 장애 발생 후에만 작동하므로 효과가 없으며,
장애가 발생했을 때는 이미 예방 조치를 취하기에 너무 늦습니다.
따라서 NGINX 오픈 소스는 회로 차단기 패턴을 지원하지 않으며, 수동 건강 검사만 가능합니다.
반면, NGINX Plus는 상태를 모니터링하고 문제를 감지하여 대응할 수 있는 강력한 액티브헬스체크 시스템을 갖추고 있습니다.
아래는 Microservices Reference Architecture의 구현 사례 중 하나를 통해
회로 차단기를 어떻게 구성할 수 있는지 설명합니다.
업로더와 리사이저의 예시
이미지를 객체 저장소에 업로드한 후, 리사이저가 해당 이미지를 열고 수정 및 크기를 조정하도록 지시하는 업로더 서비스를 예로 들어보겠습니다.
리사이저는 컴퓨팅 및 메모리 사용량이 높은 작업을 수행하므로, 업로더는 리사이저의 상태를 지속적으로 모니터링하여 과부하를 방지해야 합니다.
과부하는 실행 중인 호스트를 죽일 수도 있기 때문입니다.
1. 리사이저 상태 확인을 위한 location 블록 생성
리사이저 상태를 확인하는 블록을 정의합니다.
이 블록은 internal 위치로 설정되므로 서버의 표준 URL(http://example.com/health-check-resizer)을 통해 직접 요청할 수 없습니다.
대신, 상태 확인 정보를 위한 플레이스홀더 역할을 합니다.
2. 상태 확인 설정
이 지시문은 다음과 같은 방식으로 동작합니다:
- /health URI에 3초마다 상태 확인을 보냅니다.
- 블록에 정의된 조건(matchproxy_*)를 사용하여 서비스 인스턴스의 상태를 평가합니다.
- 단일 확인이 실패하면 해당 서비스 인스턴스를 비정상으로 표시합니다.
- HTTP 1.1을 통한 TLS 1.2를 사용하여 상태 확인 요청을 리사이저 업스트림 그룹에 전송하며, 지정된 HTTP 헤더는 null로 설정됩니다.
location /health-check-resizer {
internal;
health_check uri=/health match=conditions fails=1 interval=3s;
proxy_pass https://resizer;
proxy_ssl_session_reuse on;
proxy_ssl_protocols TLSv1.2;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Accept-Encoding "";
}다음 단계는 정상 및 비정상 조건을 나타내는 응답을 지정하기 위한 조건 블록을 만드는 것입니다.
첫 번째 검사는 응답 상태 코드입니다. 에서 까지의 범위에 있으면 테스트는 다음 평가 문으로 진행됩니다.
두 번째 검사는 가 입니다 .
마지막으로 세 번째 검사는 , , 및 메트릭 값에 대한 정규 표현식 일치입니다 .
모두 정상이면 서비스가 정상으로 결정됩니다.match200399Content-Typeapplication/jsondeadlocksDiskMemory
match conditions {
status 200-399;
header Content-Type ~ "application/json";
body ~ '{
"deadlocks":{"healthy":true},
"Disk":{"healthy":true},
"Memory":{"healthy":true}
}';
}NGINX Plus 회로 차단기/상태 점검 시스템에는 또한 느린 시작 기능이 있습니다.
블록 의 리사이저 서비스에 대한 지시문 slow_start에 대한 매개변수는 리사이저 인스턴스가 처음으로 비정상 상태에서 돌아올 때
NGINX Plus에 트래픽 흐름을 조절하라고 지시합니다.
정상적인 서비스에 보낸 동일한 수의 요청으로 서비스를 강타하는 대신,
복구 중인 서비스에 대한 트래픽은 매개 변수에서 지정한 기간(이 경우 30초) 동안 정상 속도로 천천히 증가합니다.
느린 시작은 서비스가 완전한 성능으로 돌아올 가능성을 높이는 동시에 그렇지 않을 경우의 영향을 줄입니다.serverupstreamslow_start
upstream resizer {
server resizer slow_start=30s;
zone backend 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 {
# Moderated delivery 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 levels=1:2 keys_zone=oauth_cache:10m max_size=10m inactive=15s use_temp_path=off;
upstream user-manager {
server user-manager;
zone backend 64k;
least_time last_byte;
keepalive 300;
}
server {
listen 443 ssl;
location /v1/users {
proxy_pass http://user-manager;
proxy_cache oauth_cache;
proxy_cache_valid 200 30s;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
}
}그림 2에서 볼 수 있듯이, 데이터를 캐싱한다는 것은 많은 고객 데이터 요청이 마이크로서비스 인스턴스에 도달하지 못한다는 것을 의미하며,
이전에 수신되지 않았던 요청을 위한 용량이 확보됩니다.
그림 2. 캐싱은 일반적으로 마이크로서비스 인스턴스에 대한 호출을 방지하여 성능을 가속화하는 데 사용되지만
완전한 서비스 실패에 대한 서비스 연속성을 제공하는 역할도 합니다.
그러나 데이터가 변경될 수 있는 서비스(예: 사용자 관리자 서비스)의 경우, 캐시를 신중하게 관리해야 합니다.
그렇지 않으면 사용자가 프로필을 변경했음에도 불구하고 데이터가 캐시되어
일부 컨텍스트에서 오래된 데이터가 표시되는 시나리오가 발생할 수 있습니다.
합리적인 시간 초과와 이벤트적 일관성을 갖춘 고가용성 원칙을 수용하면 이 문제를 해결할 수 있습니다.
NGINX 캐시의 좋은 기능 중 하나는 서비스가 전혀 사용할 수 없더라도 캐시된 데이터를 계속 제공할 수 있다는 것입니다.
위의 스니펫에서 서비스가 가장 일반적인 네 가지 — 500 시리즈 오류 코드 중 하나로 응답하는 경우가 해당합니다.
캐싱은 서버가 다운되어도 클라이언트에 응답하는 유일한 옵션은 아닙니다.
"회로 차단기 패턴은 유연성을 제공합니다"에서 언급했듯이,
저희 고객 중 한 명은 개인화된 광고 서버가 다운될 경우를 대비해 탄력적인 솔루션이 필요했고,
캐시된 응답은 좋은 솔루션이 아니었습니다.
대신, 개인화된 서버가 다시 온라인 상태가 될 때까지 일반화된 광고를 제공하는 일반 광고 서버를 원했습니다.
이는 지시문 backup에 매개변수를 사용하여 쉽게 달성할 수 있습니다.
다음 스니펫은 personal-ad-server 도메인에 정의된 모든 서버를 사용할 수 없는 경우
generic-ad-server 도메인에 정의된 서버를 대신 사용한다는 것을 지정합니다.
upstream personal-ad-server {
server personal-ad-server;
server generic-ad-server backup;
zone backend 64k;
least_time last_byte;
keepalive 300;
}마지막으로, NGINX가 서비스의 응답 코드를 평가503 하고 개별적으로 처리할 수 있습니다.
다음 스니펫에서 서비스 가 오류를 반환하면 NGINX Plus는 요청을 대체 서비스로 보냅니다.
예를 들어, 리사이저에 이 기능이 있고 로컬 인스턴스가 과부하되거나 작동을 멈추면 요청은 리사이저의 다른 인스턴스로 전송됩니다.
location / {
error_page 503 = @fallback;
}
location @fallback {
proxy_pass http://alternative-backend;
}결론
회로 차단기 패턴은 마이크로서비스 애플리케이션에서 회복성과 제어를 제공하는 강력한 도구입니다.
NGINX Plus는 회로 차단기를 환경에 구현하기 위한 많은 기능과 옵션을 제공합니다.
회로 차단기 패턴을 구현하는 핵심은 보호하려는 서비스의 장애 프로필을 이해한 다음,
가능한 경우 장애를 가장 잘 방지하고 장애가 발생했을 때 장애의 영향을 가장 잘 완화하는 옵션을 선택하는 것입니다.
위 내용과 같이 NGINX Plus 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
작성자 메모 – 이 블로그 게시물은 시리즈 중 여섯 번째입니다.
6개의 블로그 모두와 마이크로서비스 애플리케이션을 위한 웹 프런트엔드에 대한 블로그 <.htmla>가 무료 전자책 으로 엮어졌습니다 .
마이크로서비스에 대한 다른 NGINX 리소스도 확인해 보세요.
마이크로서비스 애플리케이션 설계는 애플리케이션의 기능 방식에 큰 변화를 가져왔습니다.
마이크로서비스 아키텍처에서 "애플리케이션"은 작업을 수행하고 기능을 제공하기 위해
서로 의존하는 서비스들의 모음으로 정의됩니다.
복잡한 애플리케이션에서는 서비스 간의 의존 관계가 매우 복잡할 수 있으며,
사용자 서비스와 같이 다른 많은 서비스에 필수적인 데이터 제공 서비스의 실패는
전체 애플리케이션에 연쇄적인 장애를 초래할 가능성이 있습니다.
이를 해결하기 위한 패턴 중 하나가 바로 Circuit Breaker 패턴입니다.
이 패턴은 Martin Fowler에 의해 널리 알려졌으며,
마이크로서비스 환경에서 연쇄적인 서비스 장애를 예방하는 데 중요한 설계 방식으로 인정받고 있습니다.
Circuit Breaker 패턴은 서비스와 그 사이를 흐르는 트래픽을 모니터링하여 장애를 방지하고,
문제가 발생했을 때 영향 범위를 최소화합니다.
특히 마이크로서비스 아키텍처에서는 서비스의 연속성을 유지하면서 연쇄 장애를 방지하는 데 효과적이며,
Netflix와 같은 기업이 이를 성공적으로 채택하여 널리 알려지게 되었습니다.
현대 애플리케이션 설계의 핵심은 실패를 피하려고 하기보다는
실패가 발생할 것을 전제로 복원력을 강화하는 데 있습니다.
애플리케이션의 다양한 구성 요소와 계층 구조는 어느 한 부분에서라도 장애가 발생할 가능성을 항상 내포하고 있습니다.
따라서 실패를 예상하고, 그 영향을 완화하는 메커니즘을 구축하는 것이 애플리케이션 복원력을 높이는 데 필수적입니다.
Circuit Breaker 패턴은 우선적으로 장애를 방지하고자 합니다.
예를 들어, 서비스가 비정상 상태에 도달할 조짐을 보이면 경고 신호를 보내거나
요청을 제한하여 서비스가 복구할 시간을 확보합니다.
이후 서비스가 정상 상태로 돌아오면 요청을 점진적으로 늘려,
즉각적인 과부하로 인해 다시 장애가 발생하지 않도록 합니다.
NGINX 마이크로서비스 참조 아키텍처의 Resizer 서비스 사례를 보면,
대량의 이미지 크기 조정 작업으로 인해 메모리 부족 문제가 발생할 수 있습니다.
이를 방지하기 위해 업로더와 Resizer 서비스 사이에 Circuit Breaker를 도입했습니다.
업로더는 주기적으로 Resizer의 상태를 확인하여 메모리 사용량이 임계치를 초과할 경우
요청을 다른 인스턴스로 전환하고, 문제가 해결되면 다시 로드 밸런싱 풀에 추가합니다.
이러한 설계를 통해 장애를 예방하고, 사용자 경험을 보호하며, 시스템의 안정성을 유지할 수 있습니다.
회로 차단기 패턴은 일관성을 향상시킵니다
NGINX에서 회로 차단기를 구현하면 마이크로서비스 애플리케이션 전반에 걸쳐
일관적이고 유연한 관리 계층을 제공할 수 있습니다.
이는 개별 언어별 회로 차단기 라이브러리에서 발생할 수 있는 뉘앙스나 불일치를 직접 처리할 필요를 없애줍니다.
특히 NGINX Plus를 활용하여 각 서비스의 코드에서 회로 차단기 기능을 제거하고 중앙에서 관리하면
다음과 같은 이점을 얻을 수 있습니다:
Java로 작성된 서비스의 회로 차단기는 PHP로 작성된 서비스와 동일하게 작동합니다.
이는 회로 차단기가 특정 언어에 국한되지 않고 다양한 언어에서도 유연하게 활용 가능함을 의미합니다.
각 서비스에서 별도로 회로 차단기 기능을 구현할 필요가 없어 언어 별로 라이브러리를 다시 작성하거나 유지 관리할 부담이 줄어듭니다.
각 서비스는 회로 차단기 관련 코드를 포함하지 않음으로써 더 단순해지고 실행 속도가 빨라지며 작성, 디버깅, 유지 관리가 쉬워집니다.
서비스 지원 코드는 서비스의 핵심 기능만을 반영하며, 사용되는 라이브러리나 시스템 구성 요소도 단순화됩니다.
회로 차단기 코드는 한 곳에서 관리되며, 지역적 상황에 맞춘 조정 없이 필수적인 기능만으로 축소됩니다.
NGINX Plus의 기능(예: 캐싱)을 활용하여 더욱 강력한 회로 차단기를 구현할 수 있습니다.
NGINX Plus에서 최적화된 회로 차단기 코드는 온프레미스, 클라우드, 하이브리드 환경 등 다양한 배포 플랫폼에서 재사용할 수 있습니다.
다만, 진정한 회로 차단기는 NGINX Plus만으로 구현할 수는 없습니다.
회로 차단기를 제대로 활용하려면 서비스에서 특정 URI(일반적으로 /health)를 통해 상태 검사를 제공해야 합니다.
상태 검사는 서비스의 특성에 맞게 설계되어야 하며, 이를 통해 장애를 사전에 파악하고 대응할 수 있습니다.
상태 점검 개발 시 고려 사항
상태 점검을 설계할 때는 서비스의 실패 패턴과 장애를 유발할 수 있는 조건
(예: 데이터베이스 연결 실패, 메모리 부족, 디스크 공간 부족, CPU 과부하 등)을 면밀히 이해해야 합니다.
이러한 조건은 상태 점검 프로세스에서 평가되며, 그 결과로 서비스의 정상 또는 비정상 상태를 결정합니다.
회로 차단기 패턴은 유연성을 제공합니다
여기에서 설명한 것처럼, NGINX 레벨에서 회로 차단기 패턴을 구현하면
서비스 인스턴스가 비정상 상태라고 통신할 때 해당 상황을 처리하는 것은 NGINX Plus의 역할입니다.
이를 위해 제공되는 여러 옵션이 있습니다.
요청 리디렉션:
요청을 다른 건강한 인스턴스로 리디렉션하고, 동시에 건강하지 않은 인스턴스에 대한 쿼리를 계속 수행하여 복구 여부를 확인합니다.
캐시된 응답 제공:
서비스를 요청하는 클라이언트에 캐시된 응답을 제공하여 서비스가 비정상적이더라도 안정성을 유지합니다.
이 방법은 콘텐츠 서비스와 같은 읽기 중심 서비스에 적합합니다.
대체 데이터 소스 제공:
예를 들어, 프로필 데이터를 활용해 타겟팅 광고를 제공하는 개인화된 광고 서버가 다운될 경우,
모든 사용자에게 적합한 일반적인 광고를 제공하는 백업 서버로 요청을 리디렉션할 수 있습니다.
이 대체 데이터 소스 방식은 매우 강력한 솔루션이 될 수 있습니다.
속도 제한:
서비스의 실패 프로필을 명확히 이해했다면, 회로 차단기에 속도 제한을 추가하여
요청이 처리 가능한 속도로만 허용되도록 설정할 수 있습니다.
이를 통해 회로 차단기 내에 트래픽 급증을 흡수할 수 있는 버퍼를 생성할 수 있습니다.
속도 제한은 라우터 메시 모델과 같은 중앙 집중형 부하 분산 시나리오에서 특히 효과적입니다.
이 모델에서는 사이트의 총 트래픽 사용량을 잘 파악할 수 있는
소수의 부하 분산 장치를 통해 애플리케이션 트래픽이 라우팅됩니다.
NGINX Plus에서 회로 차단기 패턴 구현
앞서 설명한 대로, 회로 차단기 패턴은
비정상적인 서비스로 향하는 트래픽을 줄이거나 이를 회피함으로써
장애를 미연에 방지할 수 있습니다.
이를 위해서는 각 서비스에 내장된 활성 건강 검사와 연결된 상태 모니터링이 필요합니다.
수동 건강 검사는 장애 발생 후에만 작동하므로 효과가 없으며,
장애가 발생했을 때는 이미 예방 조치를 취하기에 너무 늦습니다.
따라서 NGINX 오픈 소스는 회로 차단기 패턴을 지원하지 않으며, 수동 건강 검사만 가능합니다.
반면, NGINX Plus는 상태를 모니터링하고 문제를 감지하여 대응할 수 있는 강력한 액티브헬스체크 시스템을 갖추고 있습니다.
아래는 Microservices Reference Architecture의 구현 사례 중 하나를 통해
회로 차단기를 어떻게 구성할 수 있는지 설명합니다.
업로더와 리사이저의 예시
이미지를 객체 저장소에 업로드한 후, 리사이저가 해당 이미지를 열고 수정 및 크기를 조정하도록 지시하는 업로더 서비스를 예로 들어보겠습니다.
리사이저는 컴퓨팅 및 메모리 사용량이 높은 작업을 수행하므로, 업로더는 리사이저의 상태를 지속적으로 모니터링하여 과부하를 방지해야 합니다.
과부하는 실행 중인 호스트를 죽일 수도 있기 때문입니다.
1. 리사이저 상태 확인을 위한 location 블록 생성
리사이저 상태를 확인하는 블록을 정의합니다.
이 블록은 internal 위치로 설정되므로 서버의 표준 URL(http://example.com/health-check-resizer)을 통해 직접 요청할 수 없습니다.
대신, 상태 확인 정보를 위한 플레이스홀더 역할을 합니다.
2. 상태 확인 설정
이 지시문은 다음과 같은 방식으로 동작합니다:
location /health-check-resizer { internal; health_check uri=/health match=conditions fails=1 interval=3s; proxy_pass https://resizer; proxy_ssl_session_reuse on; proxy_ssl_protocols TLSv1.2; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Accept-Encoding ""; }다음 단계는 정상 및 비정상 조건을 나타내는 응답을 지정하기 위한 조건 블록을 만드는 것입니다.
첫 번째 검사는 응답 상태 코드입니다. 에서 까지의 범위에 있으면 테스트는 다음 평가 문으로 진행됩니다.
두 번째 검사는 가 입니다 .
마지막으로 세 번째 검사는 , , 및 메트릭 값에 대한 정규 표현식 일치입니다 .
모두 정상이면 서비스가 정상으로 결정됩니다.match200399Content-Typeapplication/jsondeadlocksDiskMemory
match conditions { status 200-399; header Content-Type ~ "application/json"; body ~ '{ "deadlocks":{"healthy":true}, "Disk":{"healthy":true}, "Memory":{"healthy":true} }'; }NGINX Plus 회로 차단기/상태 점검 시스템에는 또한 느린 시작 기능이 있습니다.
블록 의 리사이저 서비스에 대한 지시문 slow_start에 대한 매개변수는 리사이저 인스턴스가 처음으로 비정상 상태에서 돌아올 때
NGINX Plus에 트래픽 흐름을 조절하라고 지시합니다.
정상적인 서비스에 보낸 동일한 수의 요청으로 서비스를 강타하는 대신,
복구 중인 서비스에 대한 트래픽은 매개 변수에서 지정한 기간(이 경우 30초) 동안 정상 속도로 천천히 증가합니다.
느린 시작은 서비스가 완전한 성능으로 돌아올 가능성을 높이는 동시에 그렇지 않을 경우의 영향을 줄입니다.serverupstreamslow_start
upstream resizer { server resizer slow_start=30s; zone backend 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 { # Moderated delivery 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 levels=1:2 keys_zone=oauth_cache:10m max_size=10m inactive=15s use_temp_path=off; upstream user-manager { server user-manager; zone backend 64k; least_time last_byte; keepalive 300; } server { listen 443 ssl; location /v1/users { proxy_pass http://user-manager; proxy_cache oauth_cache; proxy_cache_valid 200 30s; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; } }그림 2에서 볼 수 있듯이, 데이터를 캐싱한다는 것은 많은 고객 데이터 요청이 마이크로서비스 인스턴스에 도달하지 못한다는 것을 의미하며,
이전에 수신되지 않았던 요청을 위한 용량이 확보됩니다.
완전한 서비스 실패에 대한 서비스 연속성을 제공하는 역할도 합니다.
그러나 데이터가 변경될 수 있는 서비스(예: 사용자 관리자 서비스)의 경우, 캐시를 신중하게 관리해야 합니다.
그렇지 않으면 사용자가 프로필을 변경했음에도 불구하고 데이터가 캐시되어
일부 컨텍스트에서 오래된 데이터가 표시되는 시나리오가 발생할 수 있습니다.
합리적인 시간 초과와 이벤트적 일관성을 갖춘 고가용성 원칙을 수용하면 이 문제를 해결할 수 있습니다.
NGINX 캐시의 좋은 기능 중 하나는 서비스가 전혀 사용할 수 없더라도 캐시된 데이터를 계속 제공할 수 있다는 것입니다.
위의 스니펫에서 서비스가 가장 일반적인 네 가지 — 500 시리즈 오류 코드 중 하나로 응답하는 경우가 해당합니다.
캐싱은 서버가 다운되어도 클라이언트에 응답하는 유일한 옵션은 아닙니다.
"회로 차단기 패턴은 유연성을 제공합니다"에서 언급했듯이,
저희 고객 중 한 명은 개인화된 광고 서버가 다운될 경우를 대비해 탄력적인 솔루션이 필요했고,
캐시된 응답은 좋은 솔루션이 아니었습니다.
대신, 개인화된 서버가 다시 온라인 상태가 될 때까지 일반화된 광고를 제공하는 일반 광고 서버를 원했습니다.
이는 지시문 backup에 매개변수를 사용하여 쉽게 달성할 수 있습니다.
다음 스니펫은 personal-ad-server 도메인에 정의된 모든 서버를 사용할 수 없는 경우
generic-ad-server 도메인에 정의된 서버를 대신 사용한다는 것을 지정합니다.
upstream personal-ad-server { server personal-ad-server; server generic-ad-server backup; zone backend 64k; least_time last_byte; keepalive 300; }마지막으로, NGINX가 서비스의 응답 코드를 평가503 하고 개별적으로 처리할 수 있습니다.
다음 스니펫에서 서비스 가 오류를 반환하면 NGINX Plus는 요청을 대체 서비스로 보냅니다.
예를 들어, 리사이저에 이 기능이 있고 로컬 인스턴스가 과부하되거나 작동을 멈추면 요청은 리사이저의 다른 인스턴스로 전송됩니다.
location / { error_page 503 = @fallback; } location @fallback { proxy_pass http://alternative-backend; }결론
회로 차단기 패턴은 마이크로서비스 애플리케이션에서 회복성과 제어를 제공하는 강력한 도구입니다.
NGINX Plus는 회로 차단기를 환경에 구현하기 위한 많은 기능과 옵션을 제공합니다.
회로 차단기 패턴을 구현하는 핵심은 보호하려는 서비스의 장애 프로필을 이해한 다음,
가능한 경우 장애를 가장 잘 방지하고 장애가 발생했을 때 장애의 영향을 가장 잘 완화하는 옵션을 선택하는 것입니다.
위 내용과 같이 NGINX Plus 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기