코딩공작소
MSA(6) - 서비스 디스커버리 본문
서비스 디스커버리란 ?
애플리케이션이 사용하는 모든 원격 서비스의 주소가 포함된 프로퍼티 파일을 관리하는 것 처럼 단순하거나 저장소처럼 정형화된 것일 수 있다.
- 수평확장 : 서비스 내 더 많은 서비스 인스턴스 및 컨테이너를 추가하는 것과 같은 조정
- 회복성 : 비즈니스에 영향을 주지 않고 아키텍처와 서비스 내부의 문제로 충격을 흡수하는 능력
즉, 디스커버리의 이점은 해당 환경에서 실행 중인 서비스 인스턴스의 수를 빠르게 수평 확장할 수 있다.
또한, 회복성을 향상시켜 엔진이 사용 불가한 서비스를 우회해서 라우팅하기 때문에 다운된 서비스로 입은 피해를 최소화한다.
기존의 로드 밸런서에 대해
로드 밸런서는 중앙 집중식 네트워크 인프라스트럭처로 처리할 수 있는 대부분의 애플리케이션 크기와 규모를 가진 기업 환경에서 잘 작동한다. SSL 종료를 처리하고 서비스 포트 보안을 관리하는 데 여전히 중요한 역할을 한다.
하지만,
단일 장애 지점을 제공할 수 있고, 수평 확장 능력이 제한된다. 대부분 고정적으로 관리되고 있으며 새로운 서비스 인스턴스가 시작할 때 로드 밸런서에 등록되지 않는다.
클라우드에서 서비스 디스커버리
- 고가용성 : 모든 인스턴스는 고가용성, 안정성, 확장성을 제공하고자 동일한 구성을 갖고 협업한다
- P2P : 모든 노드는 서비스의 인스턴스의 상태를 상호 공유한다
- 부하분산 : 요청을 동적으로 분산시켜 관리하고 있는 모든 서비스 인스턴스에 분배
- 회복성 : 로켈에 캐싱하며, 디스커버리 서비스가 가용하지 않아도 애플리케이션은 여전히 작동할 수 있고 로컬 캐시에 저장된 정보를 기반으로 서비스를 찾을 수 있다.
- 결함 내성 : 결함을 탐지하고 사람의 개입없이 조치되어야 한다
서비스 디스커버리 아키텍처
- 서비스 등록 : 디스커버리 에이전트에 등록
- 클라이언트의 서비스 주소 검색
- 정보 공유 : 노드 간 서비스 정보를 공유
- 상태 모니터링 : 서비스가 서비스 디스커버리에 상태를 전달하는 방법
서비스는 일반적으로 하나의 서비스 디스커버리 인스턴스에만 등록하며 클러스터 내 다른 노드에 전달하는 데이터 전파 방법으로 P2P모델을 사용한다.
더욱 견고한 접근 방법으로는 클라이언트 측 로드 밸런싱이 있다. 유레카와 함께 클라이언트 측 로드 밸런싱을 사용하는 장점은 서비스 인스턴스가 다운되면, 인스턴스가 레지스트리에서 제거된다는 것이다. 클라이언트 측 로드 밸런서는 레지스트리 서비스와 지속적으로 통신하여 자동으로 레지스트리를 업데이트한다.
- 디스커버리 서비스와 소통한 후 데이터를 서비스 소비자의 머신 로컬에 저장
- 캐시에서 서비스 위치 정보를 검색 -> 여러 서비스 인스턴스에 분배되도록 라운드 로빈 부하 분산 알고리즘처럼 단순한 알고리즘 사용
- 클라이언트는 주기적으로 서비스 디스커버리 서비스와 소통해서 서비스 인스턴스에 대한 캐시 갱신
스프링과 넷플릭스 유레카를 사용한 서비스 디스커버리
클라이언트 측 로드 밸런싱을 위해 스프링 클라우드 로드 밸런서를 사용
조직 서비스의 실제 위치는 서비스 디스커버리 레지스트리에 보관 -> 로드 밸런싱을 사용하여 각 서비스 인스턴스에서 레지스트리를 검색하고 캐시
스프링 유레카 구축
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.optimagrowth</groupId>
<artifactId>eurekaserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Eureka Server</name>
<description>Eureka Server</description>
<properties>
<java.version>11</java.version>
<docker.image.prefix>ostock</docker.image.prefix>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency> --> 애플리케이션 구성을 검색하려고 스프링 컨피그 서버에 연결하는 클라이언트를 include하도록 메이븐에 지시
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> --> 유레카에 라이브러리를 include하도록 메이븐에 지시
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</exclusion>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-eureka</artifactId>
</exclusion>
</exclusions> --> 넷플릭스 리본 라이브러리를 exclude한다
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency> --> 스프링 클라우드 로드 밸런서 라이브러리를 include하도록 메이븐에 지시
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- This plugin is used to create a docker image and publish the image to docker hub-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
|
cs |
1
2
3
4
5
6
7
8
9
|
spring:
application:
name: eureka-server --> 스프링 클라우드 컨피그 클라이언트가 찾고 있는 서비스를 알 수 있도록 유레카 서비스의 이름을 지정
cloud:
config:
uri: http://configserver:8071 --> 스프링 클라우드 컨피그 서버의 위치를 지정
loadbalancer: --> 여전히 리본이 클라이언트 측 기본 로드 밸런서이므로 loadbalancer.ribbon.enabled를 사용하여 리본을 비활성화한다
ribbon:
enabled: false
|
cs |
이는 스프링 컨피그 서버에서 구성을 검색하는 데 필요한 설정이며 src/main/resources/bootstrap.yml파일에 구성해야 한다.
src/main/resources/config/eureka-server.yml 파일 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
|
server :
port : 8070 --> 유레카 서버의 수신 포트를 설정
eureka :
instance :
hostname : eurekaserver --> 유레카 인스턴스의 호스트 이름 설정
client :
registerWithEureka : false --> 컨피그 서버가 유레카 서비스에 등록하지 않도록 지시
fetchRegistry : false --> 컨피그 서버가 레지스트리 정보를 로컬에 캐시하지 않도록 지시
serviceUrl :
defaultZone : --> 서비스 URL을 제공
http://${eureka.instance.hostname}:${server.port}/eureka/
server :
saitTimeInMsWhenSyncEmpty : --> 서버가 요청을 받기 전 초기 대기 시간을
|
cs |
- server.port : 기본 포트를 설정
- eureka.instance.hostname : 유레카 서비스의 인스턴스 호스트 이름 설정
- eureka.client.registerWithEureka : 스프링 부트로 된 유레카 애플리케이션이 시작할 때 컨피스 서버를 유레카에 등록하지 않도록 설정
- eureka.client.fetchRegistry : 유레카 서비스가 시작할 때 레지스트리 정보를 로컬에 캐싱하지 않도록 설정
- eureka.client.serviceUrl.defaultZone : 모든 클라이언트에 대한 서비스 URL 제공
- eureka.server.waitTimeInMsWhenSyncEmpty : 서버가 요청을 받기 전 대기 시간 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.optimagrowth.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer --> 스프링 서비스에서 유레카 서버를 활성화
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
|
cs |
스프링 컨피그 서비스를 먼저 실행해야 한다
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId> --> 유레카 라이브러리를 포함하여 서비스가 유레카에 등록할 수 있게 한다.
spring-cloud-starter-netflix-eureka-client
</artifactId>
</dependency>
조직 및 라이선싱 서비스의 pom.xml 파일에 스프링 유레카 의존성을 추가
그리고 각 조직/라이선싱 서비스의 bootstrap.yml 파일에 application.name을 추가해야한다.
spring :
application :
name : organization-service -> 유레카에 등록될 서비스의 논리적 이름
profiles:
active : dev
cloud :
config :
uri : http://localhost:8071
spring :
application :
name : licensing-service --> 유레카에 등록될 서비스의 논리적 이름
profiles:
active : dev
cloud :
config :
uri : http://localhost:8071
.
.
.
유레카 REST API
http://localhost:8070/eureka/apps/organization-service 엔드포인트를 호출하게 되면
인스턴스 IP주소와 현재 작동상태를 알 수 있다.
- Discovery : RestTemplate 클래스를 사용하여 조직 서비스 호출
- Rest : 향상된 스프링 RestTemplate으로 로드 밸랜서를 사용하는 서비스 호출
- Feign : 넷플릭스 Feign 클라이언트 라이브러리를 사용
1. Discovery 사용
@EnableDiscoveryClient 애너테이션 추가
Discovery Client 및 스프링 클라우드 로드 밸런서 라이브러리 사용
여기서는 DiscoveryClient를 통해 밸런서와 상호 작용한다. 또한 ServiceInstance 클래스를 사용하여 서비스를 호출하는 데 쓸 수 있는 대상 URL를 만든다. 표준 스프링 RestTemplate으로 조직 서비스를 호출하고 데이터를 조회할 수 있다.
2. 로드 밸런서를 지원하는 스프링 REST 템플릿으로 서비스 호출
RestTemplate 클래스를 사용하려면 @LoadBalanced 애너테이션으로 RestTemplate 빈을 정의해야 한다. 해당 방식을 통하면 서비스 인스턴스에 대한 모든 요청을 라운드 로빈 방식으로 부하분산한다.
3. 넷플릭스 Feign 클라이언트로 서비스 호출
@EnableFeignClients를 사용한다.
그리고 클라이언트에 @FeignClient 애너테이션을 통해 서비스를 알려준다. 나머지 코드는 Feign 클라이언트가 대신해준다.
- 서비스 디스커버리 패턴을 사용하여 서비스의 물리적 위치를 추상화
- 유레카 같은 서비스 디스커버리 엔진은 클라이언트에 영향을 주지 않고 해당 환경에서 서비스 인스턴스를 원활하게 추가하고 삭제할 수 있다
- 클라이언트 측 로드 밸런싱을 사용하면 서비스 호출을 수행하는 클라이언트에서 서비스의 물리척 위치를 캐싱하여 더 높은 성능 및 회복성을 제공할 수 있다
- 유레카는 스프링 클라우드와 함께 사용할 때 쉽게 구축하고 구성할 수 있는 넷플릭스 프로젝트다
'어플리케이션개발 > MSA' 카테고리의 다른 글
MSA(8) - 게이트웨이를 이용한 서비스 라우팅 (0) | 2024.07.16 |
---|---|
MSA(7) - Resilience4j를 사용한 회복성 패턴 (1) | 2024.07.14 |
MSA(5) - 스프링 클라우드 컨피그 서버 구성관리 (0) | 2024.07.03 |
MSA(4) - 도커 (0) | 2024.06.25 |
MSA(3) - 스프링 부트로 마이크로서비스 구축하기 (0) | 2024.06.25 |