Springboot MSA 구성3 - Spring Cloud Eureka
Spring Cloud Eureka는 MSA 시스템에서 서비스의 로드밸런싱과 실패처리 등을 유연하게 하기 위해 각 서비스들의 IP,PORT,InstanceId를 가지고 있는 REST 기반의 미들웨어 서버이다. Eureka는 마이크로 서비스 기반의 아키텍처의 핵심 원칙 중 하나인 Service Discovery의 역할을 수행한다. MSA에서는 Service의 IP와 Port가 일정하지 않고 지속적을 변화한다. Eureka는 Client-Server의 방식으로 Eureka Server는 모든 Client 서버들이 본인의 IP와 Port, InstanceId를 Eureka-Server로 전달한다. 그리고 Eureka에 있는 정보를 Fetch하여 Eureka-Client간 통신에 사용한다.
Eureka 서버
build.gradle
공통으로 사용하는 Dependency는 전체소스를 내려받아서 확인하면 되고 여기서는 Eureka 모듈에서 사용하는 Dependency만을 정리한다.
project(':Eureka') {
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
}
Application.java
EnableEurekaServer 어노테이션을 설정한다.
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
bootstrap.yml
server:
port: 8761
spring:
application:
name: eureka
eureka:
client:
registerWithEureka: true
fetchRegistry: false
Eureka의 설정정보를 Config 서버에서 가져오도록 Config서버에 EurekaClient 설정을 하게 되면 Config서버와 Eureka 서버간의 Dependency가 생기게 되기 떄문에 설정을 하지는 않는다.
Eureka 대시보드 확인
Eureka 서버의 기본설정은 여기까지이고 -Dspring.profiles.active=local 파라미터를 주고 서버를 구동하고 대시보드에 접속한다.
Eureka 대시보드 접속 - http://localhost:8761
Eureka Discovery에 클라이언트 서비스 등록
gateway, resource, resource2 모듈에 eureka client 설정을 추가한다.
build.gradle
gateway, resource, reource2 모듈에 spring-cloud-starter-netflix-eureka-client dependency를 추가한다.
project(':Gateway') {
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
}
project(':Resource') {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
}
project(':Resource2') {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
}
Application.jva 설정
resource
@EnableDiscoveryClient
@SpringBootApplication
public class ResourceApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class, args);
}
}
resource2
@EnableDiscoveryClient
@SpringBootApplication
public class Resource2Application {
public static void main(String[] args) {
SpringApplication.run(Resource2Application.class, args);
}
}
gateway
@EnableDiscoveryClient
@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
Eureka 대시보드 확인
gateway, resource, resource2 모듈을 재기동하고 대시보드를 확인한다.
Eureka 대시보드 접속 - http://localhost:8761
Eureka Discovery 활용1
config-repo 모듈의 gateway 관련 설정 중 zuul관련설정을 변경한다.
# 변경전
zuul:
routes:
member:
stripPrefix: false
path: /v1/member/**
url: http://localhost:8080
serviceId: resource
pay:
stripPrefix: false
path: /v1/pay/**
url: http://localhost:8081
serviceId: resource2
else:
stripPrefix: false
path: /v1/**
url: http://localhost:8081
serviceId: resource2
---
#변경후
zuul:
routes:
member:
stripPrefix: false
path: /v1/member/**
serviceId: resource
pay:
stripPrefix: false
path: /v1/pay/**
serviceId: resource2
else:
stripPrefix: false
path: /v1/**
serviceId: resource2
재배포 없이 실시간 반영을 위한 gateway 서버의 /actuator/refresh API를 호출한다.
POST http://localhost:9100/actuator/refresh
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 26 Aug 2021 06:07:53 GMT
Keep-Alive: timeout=60
Connection: keep-alive
[
"config.client.version",
"zuul.routes.member.url",
"zuul.routes.else.url",
"zuul.routes.pay.url"
]
Response code: 200; Time: 7755ms; Content length: 95 bytes
IP,PORT 접속정보 제거후 serviceId 접속테스트
GET http://localhost:9100/v1/member/health
HTTP/1.1 200
Date: Thu, 26 Aug 2021 06:08:43 GMT
Keep-Alive: timeout=60
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
MemberController running
Response code: 200; Time: 1087ms; Content length: 24 bytes
Eureka Discovery 활용2
Config 서버의 정보도 Eureka에 등록하고 활용하는 테스트를 진행해 보겠다.
build.gradle
Config 모듈에도 spring-cloud-starter-netflix-eureka-client Dependency를 추가한다.
project(':Config') {
dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
}
Applicaiton.java 설정
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
모듈의 config 서버정보 config.uri > config.discovery.service.id로 변경
#변경전
spring:
application:
name: resource
cloud:
config:
uri: http://localhost:9000
---
#변경후
spring:
application:
name: resource
cloud:
config:
fail-fast: true
discovery:
service-id: config
enabled: true
# uri: http://localhost:9000
Eureka 대시보드 확인
Eureka 대시보드에서 Config 서버 등록 확인.
config 서버 service명으로 접속 확인
resource, reource2 서버의 config서버의 설정 파일에 설정 값을 읽어오는 API 호출 시 정상 응답 확인.
GET http://localhost:9100/v1/resource2/message
HTTP/1.1 200
Date: Thu, 26 Aug 2021 07:30:23 GMT
Keep-Alive: timeout=60
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Resource2Controller message : Resource2 Service Local Server!!!!!
Response code: 200; Time: 470ms; Content length: 65 bytes
Eureka Discovery 활용3
Resource2 서버의 요청이 많아서 서버의 증설이 필요한 상황을 가정해서 Service 모듈을 추가하는 과정을 정리해 보려고 한다.
실행 가능한 jar파일 생성
IntelliJ의 Gradle bootJar를 실행해서 실행가능한 jar파일을 생성한다.
jar 파일 실행
$ java -jar -Dserver.port=8082 -Dspring.profiles.active=local C:\projects\Springboot-MSA\Resource2\build\libs\Resource2-0.01-SNAPSHOT.jar
Eureka 대시보드 확인
8082 포트로 실행한 Resource2 서비스 추가확인
테스트
2번의 요청을 날렸는데 8081, 8082로 한번씩 로드밸런싱 되어 요청을 한다.
GET http://localhost:9100/v1/resource2/message
HTTP/1.1 200
Date: Thu, 26 Aug 2021 09:18:16 GMT
Keep-Alive: timeout=60
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Resource2Controller message : Resource2 Service Local Server!!!!! | port: 8082
Response code: 200; Time: 317ms; Content length: 79 bytes
GET http://localhost:9100/v1/resource2/message
HTTP/1.1 200
Date: Thu, 26 Aug 2021 09:19:27 GMT
Keep-Alive: timeout=60
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Resource2Controller message : Resource2 Service Local Server!!!!! | port: 8081
Response code: 200; Time: 411ms; Content length: 79 bytes
참고
DaddyProgrammer Spring CLoud MSA(3) - Service Discovery by Eureka