[MSA] Spring Cloud Gateway (4) - Load Balancer
++) 해당 포스팅은 Eureka (Service Discovery)를 연동하여 프로젝트를 진행합니다.
사전 포스팅 참고.
Load Balancer
로드 발란서가 무엇임?
왼쪽 그림을 참고해보자.
각 서비스 A와 B는 n개의 인스턴스로 돌아가고 있다. (여러 서버를 돌리고 있다는 뜻)
특정 이벤트로 사용자가 서버에 우르르 몰리게 될 때, 로드 발란서가 서버의 부하를 줄여주기 위해 사용자 접근을 여러 서버로 고르게 분산시켜주는 역할을 한다.
쉽게 말해서 교통정리 해주는 녀석임
프로젝트 구조
구조는 다음과 같다.
- API Gateway Service 프로젝트 : eureka client, 8000포트
- first Service 프로젝트 : eureka client, 8081포트
- second Service 프로젝트 : eureka client, 8082포트
- discovery Service 프로젝트 : eureka servcer, 8761포트
8000번 포트에서 각 서비스로 요청을 넘겼을 때, 유레카에 등록되어 있는 정보에 따라 API GATEWAY가 각각 해당하는 서비스로 요청을 무사히 전달하여 클라이언트가 원하는 결과를 받을 수 있다.
api Gateway-service, first-service, second-service 프로젝트 모두 위에 해당하는 디펜던시를 설정하여 클라이언트 설정에 필요한 준비를 마치자.
프로젝트 구성 - Eureka 등록하기
api Gateway-service, first-service, second-service에 각각 설정파일을 다음과 같이 등록하자.
물론, 각각 서비스에 맞는 포트 번호와 어플리케이션 이름은 맞게 변경해줘야한다.
그 후, discovery service는 유레카 서버에 맞는 설정을 왼쪽과 같이 해준다.
dependency에는 반드시 아래와 같이 서버를 추가해야한다.
spring-cloud-starter-netflix-eureka-server
그 다음 프로젝트를 구동하자. 구동 순서는
discovery -> api gateway -> first -> second
세 가지의 유레카 클라이언트 서비스들을 실행했다면, localhost:8761에 들어가 유레카 대시보드를 확인해보자.
무사히 등록된 것을 확인할 수 있다.
server:
port: 8000
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
default-filters:
- name : GlobalFilter
args :
baseMessage : Spring Cloud Gateway Global Filter
preLogger: true
postLogger: true
routes:
- id: first-service
uri: lb://MY-FIRST-SERVICE
predicates:
- Path=/first-service/**
filters:
# - AddRequestHeader=first-request, first-request-header-yml
# - AddResponseHeader=first-response, first-response-header-yml
- CustomFilter
- id: second-service
uri: lb://MY-SECOND-SERVICE
predicates:
- Path=/second-service/**
filters:
# - AddRequestHeader=second-request, second-request-header-yml
# - AddResponseHeader=second-response, second-response-header-yml
- name: CustomFilter
- name: LoggingFilter
args:
baseMessage: Hi, there.
preLogger: true
postLogger: true
api-gateway 프로젝트의 application.yml 설정파일이다.
여기서 gateway -> routes의 uri설정을 lb://유레카 서비스 등록명 으로 바꿔주도록 하자
(로드밸런싱 작업을 위해 lb로 설정하면 로드밸런싱이 진행된다.)
두 서비스와 위와 같이 welcome에 대한 서비스 처리가 있다고 가정하고 POSTMAN으로 요청을 보내보자.
야호! 8000번 포트에서 요청을 보내도 API GATEWAY가 유레카 서버에서 정보를 찾아 무시하 8081에 있는 서비스의 welcome 메소드를 호출할 것을 확인할 수 있다.
이제 설정을 마쳤으니 진정한 로드밸런싱 작업을 진행해보도록 하자.
Scaling - 각 서비스의 서버 수 2개로 가동하기
https://born2bedeveloper.tistory.com/54
해당 포스팅에서 서버 수를 늘리는 부분이 있다. 참고하지 않아도 괜찮다! (눌러주면 정말 기쁘겠지만 ㅎ)
여러 개의 방법 중에 필자는 인텔리제이의 간편한 설정 변경 탭으로 서버 수를 증설하도록 하겠다!
해당 화살표 누르고 Edit Configuration... 클릭
해당 버튼을 눌러 어플리케이션을 똑같이 복사한 후, VM 설정에 -Dserver.port=[포트번호] 를 입력해서 서버 수를 증설하자!
복사한 어플리케이션도 잊지 말고 실행해주기~ second-service도 같은 방식으로 진행하자.
인텔리제이가 아닌 사람들의 경우를 위해, 터미널에서 직접 증설하는 방식도 기재하겠다.
해당 어플리케이션 폴더로 이동한다. (이클립스나 인텔리제이의 터미널에서도 간편하게 가능하다)
단, mvn파일을 설치하고 적용해야함 (그렇다..번거롭다 매우..)
https://maven.apache.org/download.cgi
mvn clean compile package 명령어를 통해 jar파일을 만들자
tartget에 무사히 만들어져 있는 것을 확인할 수 있음
기존 8082 포트 외에 9092 포트로 second-service서버를 하나 더 돌려보자!
유레카 서버에서 서버들이 잘 증설되었는지 확인해보자!
야호! 잘 돌아간다!
MY-FIRST-SERVICE를 보면, 8081, 9091 두 개의 서버가 돌아가고 있는 것을 확인할 수 있다.
이제 이 두 개의 서버 중 어느 서버가 실행되고 있는지 현 상태로는 알 방법이 없다!
로드밸런싱이 잘 되고 있는지 알기 위해서는 port번호라던지.. 서버를 구분할 수 있는 방법이 필요하다.
first-service의 컨트롤러 내용을 바꿔보자
package com.example.firstservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/first-service")
@Slf4j
public class FirstServiceController {
Environment env;
@Autowired
public FirstServiceController(Environment env) {
this.env = env;
}
@GetMapping("/check")
public String check(HttpServletRequest request) {
log.info("Servcer port={}", request.getServerPort());
return String.format("안녕, 나는 Custom필터와 연결된 first-service야 ^_^ 포트번호 : %s"
, env.getProperty("local.server.port"));
}
}
설정 파일에서 설정해둔 port번호를 환경변수로 가져와서 출력하는 부분을 추가해줬다.
Environment 외에 롬복을 이용해 @Value 어노테이션으로도 설정 파일의 변수를 가져올 수 있다.
한 번 더 누르면?
두 포트 번호가 번갈아가며 라운드 로빈 방식으로 호출되고 있다.
즉, 로드발랜싱이 잘 이뤄지고 있음을 알 수 있다!
마지막으로 정리해보자,
- 로드발랜싱이란?
- 특정 이벤트로 사용자가 서버에 우르르 몰리게 될 때, 로드 발란서가 서버의 부하를 줄여주기 위해 사용자 접근을 여러 서버로 고르게 분산시켜주는 역할을 한다.
- 설정 방법은?
- Api gateway 설정파일 -> routes -> uri 부분에서 맨 처음을 lb://로 설정해준다.
API Gateway 정복 끝!
[참고 레퍼런스]