스프링 클라우드에서 제공하는 Eureka는 마이크로서비스 아키텍처에서 서비스의 등록, 발견, 및 관리를 위한 서비스 디스커버리 서버이다. 이를 통해 마이크로서비스 간의 통신이 효율적으로 이뤄질 수 있다.
스프링 클라우드에서 제공한 API를 참고하여 각 기업마다 구현한 코드로써, Open source의 이점을 활용하기 위해 Spring Cloud에 기부한 구현 코드이다.
그 중 하나가 Spring-cloud Eureka이다.
Eureka는 2가지로 분류되는데, Eureka Server와 Eureka Discovery Client로 구분된다.
게이트웨이 서버로만 사용할 경우, 로드 밸런싱이나 헬스 체크까지 하는데 어려움이 있어, 이를 할당한 디스커버리 서버로 로드 밸런싱 및 헬스 체크 기능을 수행하도록 한다.
server :
port : 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
위 설정은 Eureka 서버를 8761 포트로 실행하며, 서비스 등록 및 서비스 목록 조회를 위한 설정이다.
register-with-eureka
, fetch-registry
를 false로 설정하여 해당 서버는 자신을 등록하지 않고, 등록된 서비스 목록을 가져오지 않도록 설정했다.
Spring cloud Eureka는 서비스 디스커버리를 쉽게 구현할 수 있도록 해주는 라이브러리이다. 서비스 등록, 감지, 상태 모니터링 등을 통해 마이크로서비스 간의 효율적인 통신을 가능하도록 해준다.
프로젝트 생성 시 디스커버리 유레카 서버를 추가해준다.
그 다음으로 ServerApplication 에 @EnableEurekaServer 어노테이션을 추가해준다.
마지막으로, application.yml 파일에 discovery-server 관련 설정을 추가해준다.
유레카 서버에 등록할 서비스는 Eureka Discovery Client 의존성을 추가해줘야 한다.
생성된 프로젝트 ServiceApplication 클래스에 @EnableDiscoveryClient 어노테이션을 추가해준다.
위 어노테이션이 추가돼야 유레카 서버에서 클라이언트로 인식되며 통신이 가능해진다.
application.yml 파일에 마이크로서비스 포트번호와 마이크로서비스 명칭을 추가해준다.
클라이언트를 유레카 서버에 등록해준다.
실제 빌드 파일을 2개 이상 실행시켜도 되지만, 하나의 인텔리제이에서 여러 개의 서비스 인스턴스를 실행 해보자.
먼저 위 그림에서 처럼 Edit Configuration으로 이동한다.
위처럼 왼쪽에서 3번째 복사 버튼을 눌러준 뒤 apply 버튼을 통해 적용해준다.
복사 후 실행 탭을 다시 보면 이제 2개의 선택지가 있는것을 확인할 수 있다.
위의 복사된 인스턴스를 추가로 실행 시키면,
위처럼 포트 충돌로 인해 실행이 되지 않는다.
이는 본래 인스턴스에서 8003번 포트를 사용 중이기 때문이다.
이를 해결하기 위해서는
라는 해결책이 있다.
우선, 1번 부터 확인해보면
위 두가지 방법이 있는데, 일일히 yml 파일에서 port 번호를 수정해주는 것은 번거롭고, 확인하기 어렵기 때문에
Edit Configuration에서 인스턴스 생성 시 add VM Options로 포트를 추가해주도록 설정한다.
Add VM options 클릭.
-Dserver.port=포트번호
를 입력해준다.
위에서 -D는 detach 모드를 의미하며, 콘솔창을 숨기고 애플리케이션을 가동한다는 의미이다.
이는 인텔리제이 콘솔창이 하나이기 때문에, 두 개 이상을 하나의 인텔리제이에서 기동 시 콘솔창을 숨겨줘야 한다.
실제 Eureka 서버 대시보드에 아래처럼 추가된다.
포트번호를 매번 인스턴스 생성 시마다 부여하는 것도 의미는 있다.
하지만, 인스턴스 갯수가 커질수록 이를 수동으로 별도 지정하는 것은 오류가 날 확률이 높아진다.
따라서, 2번 방법으로 포트를 추가해주는 것이 더 합리적이다.
위의 방식대로 하기 위해서 먼저 server.port=0으로 수정해준다.
0번 포트는 실제로 없는 포트이기 때문에 사실상 랜덤포트를 배정하라는 의미가 된다.
복사한 인스턴스에 추가했던 포트번호 추가 설정을 지워준다.
이제 실행하면 아래처럼 포트번호가 랜덤하게 배정된다.
하지만,
실제 충돌은 없지만 실행하는 2개의 인스턴스가 명목상 0번 포트로 감지되어
위처럼 1개의 인스턴스만 실행되는 것으로 나온다.
따라서 각 인스턴스 마다 유레카에 보여지는 이름을 다르게 설정할 필요가 있다.
eureka:
instance:
instance-id: ${spring.client.cloud.hostname}:${spring.application.instance_id:${random.value}}
위처럼 yml 파일에 설정을 추가해준다.
이후 모든 서비스 인스턴스를 재실행 해주면, 포트번호를 직접 지정하지 않고도 식별된 인스턴스를 감지할 수 있더록 되었다.
기존에 first-service 와 second-service를 활용
프로젝트 생성 시점이 아닌 이미 완성된 프로젝트 디스커버리 클라이언트 등록을 위해 아래와 같은 과정으로 진행해주면 된다.
위의 Eureka Client 의존성을 build.gradle에 추가해준다.
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
먼저 gateway-server 역시 유레카에서 사용할 수 있도록 등록.
Sping Cloud Gateway에서 이제 uri를 변경해야 한다.
유레카에 등록된 이름을 그대로
lb:// 유레카 등록어플리케이션명
형식으로 변경하여 uri에 등록해주면 된다.
그 다음 포트번호를 0으로 바꿔서 랜덤포트를 활성화 시켜준 다음
컨트롤러 측에 포트번호를 보여주는 기능을 구현한다.
이렇게 되면 로드 밸런서가 어떤 서비스가 보내주는지에 따라
그때 그때 보여지는 포트번호가 달라질 것이다.
일단 유레카 서버에서 상태창에서 보여지는 이름을 어플리케이션명으로 바꾸기 위해
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
위 처럼 인스턴스 아이디를 ${spring.application.name}
으로 변경해준다.
그 다음으로 컨트롤러 쪽에서 포트번호를 감지할 수 있는 멤버변수를 추가해보겠다.
간헐적으로 서버를 재시작하면 아래와 같이 Down이라고 현재 내려가고 있는 서버 목록이 나타나는 경우가 있다.
유레카 디스커버리 서버는 클라이언트와 30초 동안 3번 통신한 후 헬스체크를 종료하기 때문에
간헐적으로 저렇게 나올 수 있지만 결국 자동으로 해결되므로 걱정하지 않아도 된다.
게이트웨이를 경유하여 port-check를 해보자
위처럼 포트 번호를 바꿔가면서 접속시켜주어 로드 밸런싱이 일어나는 것을 볼 수 있다.