정리하자면 MSA는 Monolithic Architecture에 비해 배포 용이성, 확장성, 유연성, 고가용성(SPOF 줄임), 기술 선택 자율성 등을 꼽을 수 있다. 하지만 MSA 구조를 항상 적용해야 하는 건 아니다. 설계의 복잡성뿐만 아니라 분산 트랜잭션, 분산 캐시 일치, 서비스 간 통신 비용 등 여러 극복해야 할 과제가 많다.
서비스마다 스프링 설정을 다르게 적용하기 위해 Config Server를 사용한다. 서버에 설정을 주입할 때 Valut, Private Git Repository, RDB, Redis, File 등 다양한 방법을 사용할 수 있다.
여기선 Git Repository를 private로 만들어 {애플리케이션이름-프로필.yml}
파일을 읽어 들인다. 저장소에 SSH 공개 키를 등록하고 Çonfig Server에서는 Private Key를 이용해 설정 파일에 접근할 수 있다.
implementation 'org.springframework.cloud:spring-cloud-config-server'
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
spring.application.name=ConfigServer
server.port=9000
spring.cloud.config.server.git.uri=git@github.com:ji-jjang/msa-config.git
spring.cloud.config.server.git.ignoreLocalSshSettings=true
spring.cloud.config.server.git.private-key=\
-----BEGIN RSA PRIVATE KEY-----\n\
MIIJKQIBAAKCAgEAxERtVxWXnQ0m3inzKOWpVf+ulVQpjixCubVn+MLpIQZUYoeP\n\
...생략
0OxtdUwADW7AesDVfxyszMQMGdp2tA8A8ssexRdX8NEXV7eYC0wcCiEopi65\n\
-----END RSA PRIVATE KEY-----
http://ip:port/저장소이름/저장소환경
을 통해 Config Server에 접근하며, 여기서 ip와 port는 Config Server의 값을 입력하고, 저장소 이름과 저장소 환경은 Config Repository에 해당하는 내부 파일이름을 넣어야 한다.이름-환경.yml
이름-환경.properties
localhost:9000/애플리케이션이름/환경
로 접근하면 설정 파일의 key, value 값이 JSON 형태로 표시되는 것을 확인할 수 있다.ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-config'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
server.port=8081
spring.application.name=service1
spring.profiles.active=dev
spring.config.import=optional:configserver:http://admin:1234@localhost:9000
ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
@EnableEurekaServer
어노테이션을 통해 Eureka Server로 등록한다.@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
server.port=8761
eureka.client.register-with-eureka=false # Eureka 서버가 클라이언트로서 자기 자신을 다른 Eureka 서버에 등록할지 여부
eureka.client.fetch-registry=false # Eureka 서버로부터 레지스트리 정보를 가져올지 여부
eureka.client.service-url.defaultZone=http://admin:1234@localhost:8761/eureka
localhost:8761
에 접속하면 유레카 서버 대시보드가 나타난다. 여기에 등록된 클라이언트 정보들을 볼 수 있다.ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://admin:1234@localhost:8761/eureka
ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
spring.application.name=SpringGateWay
server.port=8080
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://admin:1234@localhost:8761/eureka
server.port=8080
spring.cloud.gateway.routes[0].id=orderService
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args.pattern=/orders/**
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[1].id=userService
spring.cloud.gateway.routes[1].predicates[0].name=Path
spring.cloud.gateway.routes[1].predicates[0].args.pattern=/users/**
spring.cloud.gateway.routes[1].uri=http://localhost:8082
게이트 웨이 라우트를 0번부터 시작해서 하나씩 늘려가며 등록하면 된다.
또한, 로드밸런싱 라우팅도 진행할 수 있는데 Gateway는 오토스케일링된 인스턴스를 알 수 없으므로 먼저 Eureka Server와 연결한 뒤 Eureka Server로부터 인스턴스 정보들을 받아와야 한다.
ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://admin:1234@localhost:8761/eureka
spring.cloud.gateway.routes[0].id=orderService
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args.pattern=/orders/**
spring.cloud.gateway.routes[0].uri=lb://ORDERSERVICE