Загружаем каталог…
Загружаем каталог…
개요 오늘은 MSA에 대해서 공부를 해보았다 예전 인프런에서 공부를 해보았는데 다시 한번 검토를 하니 좋은 시간이 었고 세부적인 내용도 추가적으로 기록할 예정이다. [MSA] Spring Cloud 기반 마이크로서비스 아키텍처 핵심 개념 정리 본 포스팅은 MSA(Microservice Architecture)의 기본 개념부터 Spring Cloud 생태계, 장애 내성(Resilience4j), 중앙 설정 관리(Config Server & Bus), 그리고 분산 데이터 처리 및 K8s까지의 핵심 흐름을 정리한 글입니다. 📌 목차 MSA(Microservice Architecture) 개요 서비스 디스커버리 & API 게이트웨이 서비스 간 통신 및 로드 밸런싱 서킷 브레이커 & 장애 대응 (Resilience4j) 중앙 집중식 설정 관리 마이크로서비스 간 통신과 분산 데이터 관리 분산 추적 & 쿠버네티스 전체 구조 정리 1. MSA(Microservice Architecture) 개요 MSA란? 하나의 거대한 애플리케이션(Monolithic)을 독립적으로 개발, 배포, 유지보수할 수 있는 여러 개의 작은 서비스 단위로 분리 하는 소프트웨어 아키텍처 스타일입니다. 전환 이유 : 확장성(Scalability), 신뢰성(Fault Isolation), 빠른 개발 및 배포 속도 주요 도전 과제 : 도메인마다 서버와 DB가 분리되어 있어 시스템 복잡도 증가 운영 비용 및 네트워크 통신 비용 증가 분산 데이터 관리 및 트랜잭션 처리의 어려움 2. 서비스 디스커버리 & API 게이트웨이 서비스 디스커버리 (Eureka) MSA 환경에서는 서비스 인스턴스가 동적으로 생성되고 소멸합니다. 유레카(Eureka)는 각 서비스의 IP와 포트 정보를 동적으로 관리하고 찾아주는 중앙 등록소 역할을 합니다. @EnableEurekaServer : 유레카 서버 역할 명시 @EnableDiscoveryClient : 유레카 클라이언트로 서버에 등록됨을 명시 API 게이트웨이 (API Gateway) 클라이언트와 마이크로서비스 단 사이의 단일 진입점(Single Point of Entry) 역할을 담당합니다. 주요 역할 : 유레카에 등록된 서비스 위치를 기반으로 요청 라우팅 보안 구성 : GlobalFilter 를 구현하여 Auth 서버에서 발급한 JWT 토큰의 인증/인가 및 만료 여부를 검증 3. 서비스 간 통신 및 로드 밸런싱 FeignClient Spring Cloud에서 제공하는 선언적 HTTP 클라이언트 로, 인터페이스와 어노테이션 정의만으로 RESTful 웹 서비스를 손쉽게 호출할 수 있습니다. 클라이언트 사이드 로드 밸런싱 (Ribbon / Spring Cloud LoadBalancer) 서버 사이드 로드 밸런서(예: L4/L7 스위치) 대신, 요청을 보내는 클라이언트가 직접 여러 서버 목록 중 하나를 선택 하여 부하를 분산하는 방식입니다. [Client Service] --- (Eureka에서 서버 목록 수집) ---> [Ribbon / LoadBalancer] │ ┌──────────────────┴──────────────────┐ ▼ ▼ [Target Server A] [Target Server B] FeignClient 내부에는 로드 밸런서가 통합되어 있어 별도 구현 없이 자동 로드 밸런싱이 수행됩니다. 4. 서킷 브레이커 & 장애 대응 (Resilience4j) Circuit Breaker 외부 서비스 장애가 전체 시스템으로 전파되는 것을 막는 차단기 역할입니다. 스프링 클라우드 기본 추상화 레이어 대신, 직관적이고 가벼운 Resilience4j 라이브러리를 주로 사용합니다. Resilience4j MSA 환경에서는 특정 서비스의 장애가 다른 서비스로 전파되지 않도록 장애 격리(Fault Isolation) 가 중요하다. Spring Cloud 환경에서는 Resilience4j 를 사용해 Circuit Breaker, Retry, Rate Limiter, Bulkhead 등의 장애 대응 기능을 구현할 수 있다. 4.1 Circuit Breaker 설정 resilience4j: circuitbreaker: instances: myServiceCircuitBreaker: sliding-window-type: COUNT_BASED sliding-window-size: 10 minimum-number-of-calls: 5 failure-rate-threshold: 50 wait-duration-in-open-state: 10s permitted-number-of-calls-in-half-open-state: 3 automatic-transition-from-open-to-half-open-enabled: true 주요 설정은 다음과 같다. 설정 의미 sliding-window-type 실패율을 계산할 기준. COUNT_BASED 또는 TIME_BASED sliding-window-size 실패율 계산에 사용할 호출 범위 minimum-number-of-calls Circuit Breaker가 판단하기 위한 최소 호출 횟수 failure-rate-threshold 실패율이 해당 비율 이상이면 OPEN wait-duration-in-open-state OPEN 상태를 유지하는 시간 permitted-number-of-calls-in-half-open-state HALF_OPEN에서 허용할 테스트 호출 수 automatic-transition-from-open-to-half-open-enabled OPEN에서 HALF_OPEN으로 자동 전환할지 여부 Sliding Window Sliding Window는 Circuit Breaker가 최근 어떤 호출들을 기준으로 장애율을 계산할 것인지 를 결정한다. Sliding Window │ "최근 어떤 호출을 볼 것인가?" │ ┌──────────┴──────────┐ ↓ ↓ 실패율 계산 Slow Call 계산 │ │ ↓ ↓ failure-rate-threshold slow-call-rate-threshold │ │ └──────────┬──────────┘ ↓ 조건 충족 여부 ↓ CircuitBreaker OPEN COUNT_BASED 최근 N번의 호출 을 기준으로 판단한다. 예를 들어: sliding-window-type: COUNT_BASED sliding-window-size: 10 이라면 최근 10번의 호출을 기준으로 실패율을 계산한다. TIME_BASED 최근 N초 동안 발생한 호출 을 기준으로 판단한다. 즉, COUNT_BASED → 최근 몇 번? TIME_BASED → 최근 몇 초? 라고 이해하면 된다. Circuit Breaker 동작 Circuit Breaker는 일반적으로 다음 세 가지 상태를 가진다. CLOSED │ │ 실패율 임계치 초과 ▼ OPEN │ │ 일정 시간 경과 ▼ HALF_OPEN │ ├── 정상 → CLOSED │ └── 실패 → OPEN OPEN 상태에서는 외부 서비스에 실제 요청을 보내지 않고 호출을 차단한다. 이때 호출은 CallNotPermittedException 으로 실패할 수 있으며, Fallback을 설정했다면 Fallback 로직으로 처리할 수 있다. Fallback Fallback은 외부 서비스 호출이 실패하거나 Circuit Breaker가 요청을 차단했을 때 대체 동작을 수행하는 로직 이다. 예를 들어: @CircuitBreaker( name = "payment", fallbackMethod = "fallback" ) fun requestPayment(): PaymentResponse { return paymentClient.request() } fun fallback(e: Exception): PaymentResponse { return PaymentResponse.failed() } 역할을 구분하면 다음과 같다. Retry → 다시 시도 Circuit Breaker → 호출을 계속할지 차단할지 판단 Fallback → 호출 실패/차단 이후 무엇을 할지 결정 4.2 Event Listener를 이용한 모니터링 Circuit Breaker 내부에서는 다양한 이벤트가 발생한다. 예를 들어: Success Error State Transition Call Not Permitted 등이 있다. Event Listener는 이러한 이벤트를 받아 로그, 메트릭, 알림 등의 추가 작업 을 수행한다. ┌─────────────────────┐ │ CircuitBreaker │ │ │ │ Success │ │ Error │ │ State Transition │ │ Call Not Permitted │ └──────────┬──────────┘ │ Event ▼ ┌─────────────────────┐ │ EventListener │ │ │ │ 로그 │ │ 메트릭 │ │ 알림 │ └─────────────────────┘ 중요한 점은 Event Listener가 Circuit Breaker의 장애 대응을 수행하는 것이 아니라, Circuit Breaker에서 발생한 이벤트를 관찰하는 역할 이라는 것이다. 모니터링 Resilience4j의 메트릭을 Micrometer 등을 통해 수집하고 Prometheus와 Grafana를 연결하면 Circuit Breaker 상태를 시각화할 수 있다. Application │ ▼ Resilience4j │ ▼ Micrometer │ ▼ Prometheus │ ▼ Grafana 5. 중앙 집중식 설정 관리 MSA에서는 여러 서비스가 존재하기 때문에 각 서비스의 설정을 개별적으로 관리하면 설정 변경과 관리가 어려워진다. 이를 해결하기 위해 Spring Cloud Config 를 사용할 수 있다. 5.1 Spring Cloud Config Spring Cloud Config는 분산 시스템의 설정 파일을 중앙에서 관리할 수 있도록 해준다. 일반적으로 Git과 함께 사용한다. Git Repository │ ▼ Config Server │ ├──────────┐ ▼ ▼ Order Payment Service Service Config Server는 설정을 직접 사용하는 것이 아니라 각 마이크로서비스가 필요한 설정을 제공하는 역할 을 한다. 5.2 설정 갱신 수동 갱신 - /actuator/refresh 설정 파일의 값을 변경했다고 해서 이미 실행 중인 Spring Bean의 값이 자동으로 변경되는 것은 아니다. @RefreshScope 를 적용한 Bean은 /actuator/refresh 를 호출하여 설정을 다시 반영할 수 있다. Git │ │ 설정 변경 ▼ Config Server │ ▼ Order Service │ │ POST /actuator/refresh ▼ 설정 재조회 │ ▼ RefreshScope Bean 갱신 예를 들어: @RefreshScope @Component class PaymentProperties( @Value("\${payment.timeout}") private val timeout: Long ) 설정이 변경된 후: POST /actuator/refresh 를 호출하면 해당 Refresh Scope Bean을 다시 생성하여 변경된 설정을 반영할 수 있다. /actuator/refresh 자체가 설정을 변경하는 것은 아니다. 해당 서비스가 Config Server에서 최신 설정을 다시 가져오도록 갱신을 트리거하는 역할이다. 5.3 Spring Cloud Bus 서비스가 많아지면 각각의 서비스에 /actuator/refresh 를 호출하는 것은 번거롭다. 이때 Spring Cloud Bus를 사용할 수 있다. Spring Cloud Bus는 RabbitMQ, Kafka 등의 메시지 브로커를 이용하여 설정 변경 이벤트를 여러 서비스에 전파한다. Config Server │ │ 설정 변경 이벤트 ▼ Message Broker (RabbitMQ/Kafka) │ ┌────────┼────────┐ ▼ ▼ ▼ Order Payment Inventory │ │ │ Refresh Refresh Refresh 따라서 하나의 서비스에서 Bus Refresh 이벤트를 발생시키면 연결된 여러 서비스에 설정 변경 이벤트를 전달할 수 있다. POST /actuator/busrefresh /refresh 는 개별 서비스의 설정 갱신에 사용하고, /busrefresh 는 Spring Cloud Bus를 통해 여러 서비스에 갱신 이벤트를 전파하는 방식이다. 6. 마이크로서비스 간 통신과 분산 데이터 관리 MSA에서는 서비스마다 DB가 분리될 수 있다. 예를 들어: Order Service │ └── Order DB Payment Service │ └── Payment DB Inventory Service │ └── Inventory DB 따라서 하나의 트랜잭션으로 여러 서비스의 DB를 묶기 어려워진다. 6.1 데이터 동기화 문제 예를 들어 주문 생성 후 재고 차감이 필요한 경우: Order 생성 ↓ Inventory 차감 ↓ Payment 처리 중간 단계에서 장애가 발생하면 서비스 간 데이터 상태가 달라질 수 있다. Order DB → 주문 생성 완료 Inventory DB → 재고 차감 실패 Payment DB → 결제 처리 안 됨 이처럼 분산 환경에서는 모든 서비스를 하나의 DB 트랜잭션처럼 묶는 것이 어렵다. 해결 방향 대표적으로 다음과 같은 방법을 고려할 수 있다. 최종적 일관성(Eventual Consistency) 메시지 브로커를 이용한 비동기 이벤트 전달 Outbox Pattern Saga Pattern 보상 트랜잭션 재처리 및 DLQ 핵심은 서비스 간 데이터 일관성을 어떻게 유지할 것인가 이다. 6.2 이벤트 드리븐 아키텍처 Spring Cloud Stream 등을 이용하면 Producer와 Consumer 간 비동기 메시지 기반 통신을 구성할 수 있다. Order Service │ │ OrderCreated Event ▼ Message Broker │ ├──────────────┐ ▼ ▼ Inventory Notification Service Service Producer가 이벤트를 발행하면 Consumer가 해당 이벤트를 비동기적으로 처리한다. 이때 실제 운영 환경에서는 다음 문제를 함께 고려해야 한다. 메시지 중복 메시지 유실 Consumer 장애 재처리 순서 보장 DLQ(Dead Letter Queue) Idempotency 따라서 단순히 메시지를 발행하는 것보다 장애가 발생했을 때 어떻게 복구할 것인지 가 중요하다. 7. 분산 추적 & 쿠버네티스 7.1 Distributed Tracing MSA에서는 하나의 사용자 요청이 여러 서비스를 거칠 수 있다. Client │ ▼ Gateway │ ▼ Order │ ├──→ Payment │ └──→ Inventory Order 요청이 느려졌을 때 실제 원인이 Order인지 Payment인지 Inventory인지 확인하기 어려울 수 있다. 이때 Distributed Tracing을 사용한다. Request │ ▼ Trace ID: abc123 │ ├── Gateway ├── Order ├── Payment └── Inventory 하나의 요청에 Trace ID를 부여하고 각 서비스의 호출 정보를 연결하면 전체 요청 흐름을 추적할 수 있다. Micrometer Spring 생태계에서는 Micrometer를 이용하여 메트릭 및 관측 데이터를 다룰 수 있다. 분산 추적 환경에서는 Trace ID, Span 등의 정보를 이용해 서비스 간 요청 흐름을 연결한다. Zipkin Zipkin은 분산 시스템의 Trace 데이터를 수집하고 시각화하는 시스템이다. Gateway ↓ Order ↓ Payment ↓ Inventory 각 호출에 대한 시간을 확인하여 어느 구간에서 지연이 발생했는지 분석할 수 있다. 7.2 Kubernetes Kubernetes는 컨테이너화된 애플리케이션을 배포하고 운영하기 위한 컨테이너 오케스트레이션 플랫폼이다. MSA 환경에서는 여러 서비스와 여러 인스턴스를 운영해야 하기 때문에 Kubernetes를 활용할 수 있다. 대표적인 기능은 다음과 같다. 컨테이너 배포 서비스 디스커버리 로드 밸런싱 자동 스케일링 Self-healing Rolling Update 장애가 발생한 Pod 재시작 예를 들어 트래픽이 증가하면: 평상시 Order Pod ├── Pod 1 └── Pod 2 트래픽 증가 Order Pod ├── Pod 1 ├── Pod 2 ├── Pod 3 ├── Pod 4 └── Pod 5 HPA(Horizontal Pod Autoscaler)를 이용하면 CPU 사용량이나 기타 지표에 따라 Pod 개수를 자동으로 조절할 수 있다. 8. 전체 구조 정리 지금까지 살펴본 기술을 하나의 MSA 구조로 연결하면 다음과 같다. Client │ ▼ ┌─────────────────┐ │ API Gateway │ └────────┬────────┘ │ Load Balancer │ ┌──────────────────┼──────────────────┐ ▼ ▼ ▼ Order Service Payment Service Inventory Service │ │ │ └──────────┬───────┴──────────┬───────┘ │ │ ▼ ▼ Eureka Message Broker │ │ │ Event Driven │ │ ▼ ▼ Service Discovery Async Processing ┌─────────────────────────┐ │ Spring Cloud Config │ └────────────┬────────────┘ │ ▼ Git Observability Application │ ├── Resilience4j ├── Micrometer │ ▼ Prometheus │ ▼ Grafana Distributed Tracing Services │ ▼ Trace Data │ ▼ Zipkin 기술 요약 구분 기술 역할 Discovery Spring Cloud Eureka 서비스 인스턴스 등록 및 위치 조회 Gateway Spring Cloud Gateway 외부 요청의 진입점 및 라우팅 Communication FeignClient + LoadBalancer 서비스 간 REST 호출 및 인스턴스 부하 분산 Resilience Resilience4j Circuit Breaker 등 장애 격리 Config Spring Cloud Config 중앙 설정 관리 Config Propagation Spring Cloud Bus 설정 변경 이벤트 전파 Messaging Kafka / RabbitMQ 서비스 간 비동기 메시지 전달 Observability Micrometer + Prometheus + Grafana 메트릭 수집 및 모니터링 Tracing Micrometer Tracing + Zipkin 분산 요청 흐름 추적 Container Docker 애플리케이션 컨테이너화 Orchestration Kubernetes 컨테이너 배포 및 운영 자동화 마무리 MSA에서 중요한 것은 각각의 기술을 따로 외우는 것이 아니라 각 기술이 어떤 문제를 해결하기 위해 존재하는지 연결해서 이해하는 것 이다. 서비스가 많아짐 ↓ 서비스 위치를 어떻게 찾지? → Eureka 외부 요청을 어떻게 통제하지? → API Gateway 서비스끼리 어떻게 호출하지? → Feign + LoadBalancer 상대 서비스가 장애 나면? → Resilience4j 설정이 여러 서비스에 흩어지면? → Spring Cloud Config 설정 변경을 여러 서비스에 어떻게 전파하지? → Spring Cloud Bus 서비스 간 비동기 통신이 필요하면? → Kafka / RabbitMQ 요청이 여러 서비스를 거치면 장애 원인을 어떻게 찾지? → Distributed Tracing 서비스 인스턴스가 많아지면 어떻게 운영하지? → Kubernetes 결국 MSA의 핵심은 "기술을 많이 사용하는 것"이 아니라, 분산 시스템에서 발생하는 문제를 어떤 기술로 해결할 것인지 판단하는 것 이다.
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
TIL 2일차. 오늘 배운 점 영속성 컨텍스트에 대해 다시 공부했다. 처음 배웠을 때 이해했다고 생각했지만, 막상 튜터님이 질문했을 때 em.persist() 같은 키워드는 떠올랐지만, 영속성 컨텍스트가 무엇인지 제대로 설명하지 못했던 기억이 있다. 디버깅 과정에서 EntityManager 의 하위 객체를 확인하고, persist() 이후 엔티티가 영속성 컨텍스트에서 관리되는 과정과 find() 를 통해 조회할 때 어떤 식으로 동작하는지 직접 확인하면서 개념을 이해하는 데 도움이 됐다. 내일도 이어서 해볼 점 Spring Security를 공부하면서 오늘 배운 내용과 연결되는 개념들을 이해해볼 예정이다. 오늘 아쉬웠던 점 기존에 공부했던 내용과 새롭게 배운 내용이 뒤섞이면서 어떤 내용이 정확한지 다시…
Открыть источникTIL 2일차. 개요 오늘은 MSA에 대해서 공부를 해보았다 예전 인프런에서 공부를 해보았는데 다시 한번 검토를 하니 좋은 시간이 었고 세부적인 내용도 추가적으로 기록할 예정이다. [MSA] Spring Cloud 기반 마이크로서비스 아키텍처 핵심 개념 정리 본 포스팅은 MSA(Microservice Architecture)의 기본 개념부터 Spring Cloud 생태계, 장애 내성(Resilience4j), 중앙 설정 관리(Config Server & Bus), 그리고 분산 데이터 처리 및 K8s까지의 핵심 흐름을 정리한 글입니다. 📌 목차 MSA(Microservice Architecture) 개요 서비스 디스커버리 & API 게이트웨이 서비스 간 통신 및 로드 밸런싱 서킷 브레이커 & 장애 대응…
Открыть источник