MSA 기반의 사이드 프로젝트입니다.
- 프로젝트 기간 : 2023.02.01 - continue
- 개발환경 : Java 11, Spring Boot 2.6.7, Gradle(Build Tool), Git, MySQL
- 사용 기술
- JPA, Swagger, Handler Exception, Spring Security, JWT
- Eureka, API Gateway, Feign Client, ErrorDecoder, CircuitBreaker
- Zipkin, Spring Cloud Sleuth
- Spring Cloud Bus, Spring Actuator, RabbitMQ, Docker
- 각 서비스 Eureka Server 및 API Gateway 등록 및 도커 이미지화
- 랜덤 포트 부여
- Swagger를 활용한 API 문서 자동화
- Handler Exception 처리
- 모든 서비스 컨테이너화
- Communication
- Synchronous(동기) HTTP 통신
- 하나의 클라이언트 요청에 대해 끝나기 전까지 다른 작업을 처리하지 못한다.
- RestTemplate, FeignClient의 HTTP 통신 방법으로 구현이 가능.
- Asynchronous(비동기) 통신 AMQP
- AMQP 프로토콜을 이용해 각 마이크로서비스 간에 비동기 방식으로 통신
- 변경된 사항을 전달해주고 Service는 더 이상 관여를 하지 않는 방식
- 필자의 선택 : Feign Web Service Client(Feign Client->HTTP Client)
- REST Call 방식을 사용하기 위해 추상화되어 있는 인터페이스를 제공
- Spring Cloud Netflix에 포함되는 라이브러리
- RestTemplate보다 훨씬 직관적이고 간단
- Load Balanced 지원
- Feign Client
- Feign Logger를 활용한 Feign Client 로그 추적
- Error Decoder를 활용한 Feign Exception 처리
- Microservice 통신 연쇄 오류
- 각 서비스끼리 통신을 하다보니, 통신 연쇄 오류를 발견.
- 때문에, 통신할 서비스에서 에러 발생 시, 에러를 대신할 메소드를 만들어서 해결하는 것이 좋겠다고 판단.
- 즉, 장애 발생 시, CircuitBreaker를 이용해서 다른 기능으로 대체 수행. = 장애 회피
- Synchronous(동기) HTTP 통신
- 분산 추적
- Zipkin
- Spring Cloud Sleuth + Zipkin
- Eureka Server 구축
-
Gateway Server 구축
- Spring Cloud API Gateway는 비동기 방식으로 서비스가 실행
- 각 서비스 Load Balancer 적용
-
Custom, Global, Logging Filter Test -> Mono 사용.
- 의문점: Flux도 0~1개의 데이터 전달이 가능한데, Mono 라는 타입이 필요할까?
- 해답 : 데이터 설계 시, 결과가 없거나 하나의 결과값만 받는 것이 명백한 경우, List를 사용하지 않는 것처럼, 불필요하게 Flux를 사용하지 않고 Mono를 사용하는 것.
-
By 토비: WebFlux를 아래와 같은 용도로 사용하는 것을 추천한다.
- 비동기 : Non-Blocking Reactive 개발에 사용.
- 효율적으로 동작하는 고성능 Web Application 개발.
- Service 간 호출이 많은 MSA에 적합
-
Gateway Authorization Header filter 구현
- 모든 요청은 서비스 최전방에 위치하는,API Gateway를 통해서만 서비스에 접근 가능하기 때문에, Gateway Filter에서 인가처리하도록 구현
- 즉,모든 요청 Authorization Header에 Access Token을 담아 요청을 보내면 서버에서 일련의 인가 과정을 거쳐 Resource Server에 요청을 라우팅하도록 했다.
- User Server 구축
-
JWT 및 Spring Security 활용
- Password 인코딩 후 디비에 저장
- Login 성공 시, JWT Token 발급
- Product Server 구축
- Order Server 구축
- 분산 시스템에서 서버 클라이언트 구성에 필요한 설정 정보를 외부 시스템에서 관리를 위함.
- 하나의 중앙화된 저장소에서 구성요소 관리
- 각 서비스 재빌드를 하지 않고 바로 적용
- 애플리케이션 배포 파이프라인을 통해 환경에 맞는 구성 정보 사용
- 외부 설정 정보 활용 및 Changed Configuration Values
- Spring Cloud Starter Config 정보 가져옴.
- Actuator 사용하여, 효율적으로 application 상태 및 모니터링
- Spring Cloud Bus 사용하여, 분산 시스템의 노드(=마이크로서비스)를 경량 메시지 브로커(=RabbitMQ)와 연결하여 상태, 구성에 대한 변경 사항 연결 노드에게 전달
- SSH Key 생성하여 private git repository 접근
- AMQP(Advanced Message Queuing Protocol) 사용
- RabbitMQ 활용
- 왜 Kafka가 아닌, RabbitMQ를 선택했나?
- 최고 처리량 Kafka : 605MB/s
- 최고 처리량 RabbitMQ : 38MB/s
- Kafka는 대용량 데이터를 빠른 시간내에 처리하고자 할 때 적합.
- 하지만 해당 프로젝트는 대용량 데이터라고 하기엔 부족하기 때문에,
- 적은 데이터를 안전하게 전달하는 것을 보장해주는 RabbitMQ를 선택하게 되었다.
- 하지만, RabbitMQ는 이벤트 메시지가 성공적으로 잘 전달되면, 메시지 큐에서 삭제되기 때문에, 소비자와 브로커 결합력이 높아진다.
- 따라서 트래픽이 증가하면 수평적으로 확장하기 어려울 것 같다.
- 반면에, Kafka는 이벤트 스트림에서 계속 토픽을 유지하기 때문에, RabbitMQ에 비해 유연하고 느슨한 결합을 가진다.
- 따라서, 추후에 대규모 트래픽이 예상이 되고, 확장이 예상된다면 Kafka를 공부하고 적용해보는 시간도 가져보자.
- RabbitMQ란? 그리고 kafka와 차이점은?