중요 패턴 정리
라우팅 패턴
- 요청을 특성 시스템 or 서비스로 올바르게 전달하는 방법에 대한 패턴.
- API Gateway에서 라우팅 패턴 사용함
클라이언트 회복성 패턴
- 클라이언트가 원격 서비스의 실패나 성능 저하에 대해 복구할 수 있도록 도와 주는 패턴
- (내부 패턴) 서킷 브레이커 패턴 : 서비스 실패 or 성능 저하 -> 대체 로직 사용 or 호출 차단
- (내부 패턴) 벌크헤드 패턴 : 원격 자원 호출은 독립된 스레드 풀로 분리 자원별로 스레드 풀 격리
- 단일 장애 지점(Single Point of Failure, SPOF)을 방지
- 단일 장애 지점 : 시스템의 구성 요소 중 하나가 고장나면 전체 시스템이 중단되는 지점
- hystrix or resilience4j 라이브러리를 이용하여 해당 패턴 구현 가능
빌드 배포 패턴
- CI/CD 패턴이 대표적. 코드 변경이 발생할 때마다 자동으로 빌드를 하고 배포하여 개발 주기를 단축.
로깅 패턴
- 중앙 집중식 로깅 시스템(ELK)을 사용하면 여러 서버에서 발생하는 로그를 한 곳에 모을 수 있음.
보안 패턴
- 인증과 권한 부여 패턴을 통해 사용자 및 시스템 접근 제어.
- OAutho, JWT 인증 방식을 사용하여 보안 강화 및 서비스 간 안전한 통신 보장
기본 구조
Spring Cloud Config
- 마이크로서비스 환경에서 애플리케이션 설정 정보를 중앙 집중화하여 관리하는 시스템
- 분산된 환경의 서버에서 환경 설정 정보를 중앙에서 모아 관리를 하는데 도움을 주는 라이브러리
- yml을 모아둔 github repository에서 설정파일들을 관리함.
- 모아둔 yml파일에서는 당연히 암호화 관리 한다({chiper}사용)
- private repo로 만들어야하며, 모아둔 yml repo 접근은 ssh와 같은 방식을 이용하여 접근한다.
- Spring Cloud Config Client는 위의 서버에 주소와 파일명을 yml에 작성하여 연동
Spring Cloud Stream
- 이벤트 중심 마이크로 서비스를 구축하기 위한 프레임워크
- 외부 미들웨어와의 통신을 하기 위해서 통합 컴포넌트를 제공
- 그러기 때문에 binder, binding 이라는 개념 존재
- Spring Cloud 프로젝트에서 제공해주는 프레임워크 중 하나
- Apache Kafka 또는 RabbitMQ 등을 사용하여 Spring Boot 어플리케이션과 메세지를 보내고 받음
- (번외) 대용량 처리를 위해 설계된 kafka를 왜 사용하는가?
- kafka streams API를 제공하여서.
- 해당 라이브러리는 연속적인 이벤트 스트림 데이터를 좀 더 빠르고 간단하게 처리하여 연속적인 결과값 얻을 수 있기 때문
- 정적인 데이터를 특정시간에 일괄로 처리하는 배치 프로세싱보다 연속적임
Spring Cloud Service Discovery
- 서비스 인스턴스들을 서로 동적으로 발견하고, 네트워크 위치(IP, 포트)를 추상화하는 기능
- 클라우드 환경에서 인스턴스는 AutoScaling, 생성, 삭제, 확장 등을 거치면서 IP나 Port들이 동적으로 변경될 가능성이 있어 필요(매번 수동 변경은 불편)
- Eureka는 넷플릭스에서 개발한 서비스 디스커버리 시스템으로 가장 대표적
- 서비스 인스턴스들을 등록하고, 다른 서비스에서 해당 인스턴스를 찾아 요청 가능
- 서버 사이드 디스커버리와 클라이언트 사이드 디스커버리 방식 존재
- 클라이언트 사이드 디스커버리 : Service Registry를 통해 서비스 호출
- 서버 사이드 디스커버리 : Service Registry가 아닌 앞단의 Load Balancer를 통해 다른 서비스 호출
(로드 밸런서가 내부의 Service Registry에게 질의함으로써 결과를 반환)
- 차이 : MSA의 다른 서비스를 호출할 때 Service Registry를 통해서 다른 서비스를 호출하는가?
- Spring Cloud Netflix Eureka : Service Registry의 서버 역할, 서비스들을 등록하는 역할
- Eureka Server와 Eureka Client의 eureka.client.serviceUrl.defaultZone을 동일하게 구성하여 유레카 서버가 클라이언트들을 인식하여 알 수 있게됨
- Eureka Client는 MSA의 각 서비스들에는 모두 Eureka Clients를 추가하면 된다.
API Gateway
- 외부의 요청을 받아서 알맞는 도메인 Application에게 요청을 보내는 MSA 구성 요소
- 클라이언트와 백엔드 서비스 간의 모든 요청을 라우팅하는 단일 진입점 역할
- 인증, 권한 부여, 로깅, 트래픽 관리 등 여러 기능을 제공
- 대표 라이브러리
- Netflix Zuul : Servlet 기반 동기방식 [개발 및 유지보수 중지 상태]
- Spring Cloud Gateway : Netty 기반 비동기방식(Non-Blocking), Spring webFlux 위에서 동작
- 구성요소
Route : 클라이언트 요청 -> 특정 서비스로 전달하는 규칙 (고유 ID + 목적지 URI + Predicate + Filter로 구성)
Predicate : 라우팅 조건 정의 (시간, URI, 요청, 네트워크로 구성)
Filter : 요청 및 응답을 수정하거나 추가 작업을 수행하는 기능
Spring Cloud Gateway vs Kong, NGINX
통합성 : Spring Cloud Gateway는 Spring 생태계와의 통합성이 뛰어나지만, Kong이나 NGINX는 독립적인 API 게이트웨이 솔루션으로 더 다양한 언어와 프레임워크와의 호환성을 가진다.
확장성 : Kong과 NGINX는 고성능의 트래픽 처리를 위해 최적화되어 있으며, 대규모 분산 환경에서 유리할 수 있다.
출처
MSA 간의 서비스 연결
- 기능별로 서비스를 나눈다.
- 동기적 호출 시에는 OpenFeign을 쓴다.
- 인터페이스에 @FeignClient(name = "Feign Client 이름(member)", path = "호출할 API url (/api/member)")
- 비동기적인 메시지 브로커 방식을 많이 쓰임 (Kafka, RabbitMQ 등)
- 같이보면 좋은 사이트
링크1, 링크2, 링크3
MSA 서비스 장애 대응 (클라이언트 회복성 패턴 관련)
- 장애 대응 예시 : 요청 실패시, 요청의 Timeout 시간만큼 요청 스레드를 점유 / 응답 지연시, Latency 시간만큼 요청 스레드를 점유
- 서버의 스레드풀이 고갈되어 전체 서비스의 장애로 이어짐 / 사용자는 오랜 시간 지연 후 에러 발생
- 라이브러리
- Netflix Hystrix - 더 이상 개발 되지 않고 있음
- Resilience4J - 추천
- 각 서비스에서 적용하고 싶은 서비스에만 설정하면 된다.
- 방식 (동기적으로 구성할 경우)
- 회로 차단기 패턴 : 요청 시간 및 실패 횟수에 따라 Closed or Open 상태 전환 (시간 및 호출은 야믈에서 세팅)
@FeignClient(name = "Feign Client 이름(member)", path = "호출할 API url (/api/member)")
@CircuitBreaker(name = "circuit")
- 폴백 패턴 : Circuit Breaker가 Open 상태인 상황에서 사용자 요청을 에러로 응답하지 않고 성공(미리 설정한 응답)으로 응답
@FeignClient(name = "Feign Client 이름(member)", path = "호출할 API url (/api/member)", fallback = CustomFallback.class)
@CircuitBreaker(name = "circuit")
- 벌크헤드 패턴 : 동시 호출 요청 수 제한, 스레드폴 설정 가능
@FeignClient(name = "Feign Client 이름(member)", path = "호출할 API url (/api/member)", fallback = CustomFallback.class)
@CircuitBreaker(name = "circuit")
public class ClassName {
@GetMapping
@Bulkhead(name = "야믈에 설정한 인스턴스명", fallbackMethod = "bulkheadFallbackMethod")
publice Response functionName(String variableName);
publice Response bulkheadFallbackMethod(Throwable e);
}
출처
MSA 트랜잭션 처리
- 서비스 분리로 트랜잭션의 특성 중 하나인 원자성을 보장하기 어려워짐
- 방법
정말 유익하네요!