๐ 1. Eureka๋?
Eureka๋ Netflix์์ ๊ฐ๋ฐํ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ ๋ฐ ๋ก๋ ๋ฐธ๋ฐ์ฑ์ ์ ๊ณตํ๋ ๋๊ตฌ
์ฃผ๋ก Spring Cloud์์ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ ์๋ฃจ์ ์ผ๋ก ์ฌ์ฉ๋๋๋ฐ, ์ด ๊ฒฝ์ฐ ์๋น์ค๋ค์ด ๋์ ์ผ๋ก ๋ฑ๋ก๋๊ณ ์๋น์ค ์์น ์ ๋ณด๋ฅผ ์ค์์์ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ Gateway์์ ๊ฐ ์๋น์ค์ uri๋ฅผ ์ง์ ์ค์ ํ ํ์์๋ค.
โ Eureka์ ์ฃผ์ ๊ฐ๋
1๏ธโฃ Eureka Server
- Eureka Server๋ ์ฌ๋ฌ ๋ง์ดํฌ๋ก์๋น์ค๋ค์ด ์๋ก๋ฅผ ์ฐพ์ ์ ์๋๋ก ์๋น์ค ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์ ๊ณต.
- ์ฌ๋ฌ ๊ฐ์ Eureka ์๋ฒ๋ฅผ ํด๋ฌ์คํฐ๋งํ์ฌ ๊ณ ๊ฐ์ฉ์ฑ์ ๋ณด์ฅํ ์ ์๋ค.
2๏ธโฃ Eureka Client ( ์๋น์ค ๋ฑ๋ก & ์๋น์ค ๊ฒ์ )
- ์๋น์ค๊ฐ Eureka Server์ ์์ ์ ๋ฑ๋กํ๊ณ , ๋ค๋ฅธ ์๋น์ค๋ฅผ ์ฐพ๊ธฐ ์ํด Eureka Client๋ฅผ ์ฌ์ฉ.
- ์ฃผ๊ธฐ์ ์ผ๋ก ์์ ์ด ์คํ๋๊ณ ์๋ ํธ์คํธ์ ํฌํธ๋ฅผ Eureka Server์ ์๋ฆฐ๋ค.
- ํด๋ผ์ด์ธํธ๋ Eureka Server์์ ์ ๊ณตํ๋ ์๋น์ค ๋ชฉ๋ก์ ์กฐํํ๊ณ , ์๋น์ค ์ธ์คํด์ค๋ฅผ ์ ํํ์ฌ ํต์ ํ ์ ์๋ค.
โ Eureka์ ์ฃผ์ ์ญํ
1๏ธโฃ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ (Service Discovery)
- ํด๋ผ์ด์ธํธ๋ ๋ค๋ฅธ ์๋น์ค๊ฐ ์๋น์ค๋ฅผ ์ฐพ์ ๋, Eureka Server์์ ์๋น์ค ๋ชฉ๋ก์ ์กฐํํ์ฌ ํ์ํ ์๋น์ค์ ์์น๋ฅผ ์ฐพ์ ์ ์๋ค.
- ์ด ๋ฐฉ์์ผ๋ก ์๋น์ค๊ฐ ๋์ ์ผ๋ก ํ์ฅ๋๊ฑฐ๋ ์ถ์๋์ด๋ ํด๋ผ์ด์ธํธ๋ ์๋น์ค์ ์ค์ ์์น๋ฅผ ์ ํ์ ์์ด Eureka๋ฅผ ํตํด ์๋์ผ๋ก ์ฐพ์ ์ ์๋ค.
2๏ธโฃ ๋ก๋ ๋ฐธ๋ฐ์ฑ ๋ฐ Fault Tolerance
- Eureka๋ ์ฌ๋ฌ ์ธ์คํด์ค๊ฐ ๋ฑ๋ก๋ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ์์ ๋ผ์ด๋ ๋ก๋น(Round-Robin) ๋ฐฉ์์ผ๋ก ์์ฒญ์ ๋ถ๋ฐฐํ ์ ์๋๋ก ์ง์ํฉ๋๋ค.
- ํน์ ์๋น์ค ์ธ์คํด์ค๊ฐ ์๋ตํ์ง ์๋ ๊ฒฝ์ฐ, Eureka๋ ์ด๋ฅผ ์ ๊ฑฐํ๊ณ ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ๋๋ค.
3๏ธโฃ ์ํ ๊ฐฑ์ (heartbeat ์ฒดํฌ) & ์์ฒด ๋ณต๊ตฌ ๊ธฐ๋ฅ (Self-healing)
- Eureka Client๋ ์ผ์ ์ฃผ๊ธฐ๋ก Heartbeat ์ ํธ๋ฅผ Eureka Server์ ๋ณด๋ด ์๋น์ค ์ํ๋ฅผ ๊ฐฑ์ ํ๋ค.
- Heartbeat ์ ํธ๋ฅผ ๋ฐ์ง ๋ชปํ ๊ฒฝ์ฐ Eureka Server๋ ํด๋น ์๋น์ค๋ฅผ DOWN ์ํ๋ก ํ์ or ๋ชฉ๋ก์์ ์ ๊ฑฐ.
- ์๋น์ค๊ฐ ๋ค์ ์์๋๋ฉด Eureka์ ๋ค์ ๋ฑ๋ก๋์ด ์๋์ผ๋ก ๋ณต๊ตฌ๋๋ค.
โญ ์ธ์คํด์ค ์ํ
- ํฌ์ค์ฒดํฌ ์คํจ ์ : status Down์ผ๋ก ๋ณ๊ฒฝ
- ํฌ์ค์ฒดํฌ ์ผ์ ๊ธฐ๊ฐ(leaseExpirationDurationInSeconds, ๊ธฐ๋ณธ 90์ด) ๋์ ์คํจ: ๋ฑ๋ก ํด์
- ๋นํ์ฑํ(๊ด๋ฆฌ์ ๋๋ ์์คํ ์ด ์ค์ ): ์ ์ง๋ณด์ ๋ฑ์ ์ด์ ๋ก ์ผ์์ ์ผ๋ก ์ ์ธํ๋ ๊ฒ, ์๋น์ค๋ ์คํ ์ค ์ด์ง๋ง ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ์ง ์๋๋ก ์ค์ ๋จ.
์ํ | ์ค๋ช | Eureka์ ๋ฑ๋ก | ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ | ์๋ ๋ณต๊ตฌ |
OUT_OF_SERVICE | ์๋น์ค๊ฐ ์ผ์์ ์ผ๋ก ์ฌ์ฉ ์ค์ง๋จ (๋ณดํต ์๋ ์ค์ ) | โ (๋ฑ๋ก๋จ) | โ (์กฐํ ๋ถ๊ฐ) | โ (UP์ผ๋ก ๋ณ๊ฒฝํ๋ฉด ์ฆ์ ๋ณต๊ตฌ๋จ) |
DOWN | ์๋น์ค๊ฐ ์ฅ์ ๋ก ์ธํด ๋์ํ์ง ์์ | โ (๋ฑ๋ก๋จ) | โ (์กฐํ ๋ถ๊ฐ) | โ (UP์ผ๋ก ๋ณ๊ฒฝํ๊ฑฐ๋ ํฌ์ค ์ฒดํฌ ๋ณต๊ตฌ ์ ์๋ ๋ณต๊ตฌ) |
DEREGISTERED | ์๋น์ค๊ฐ ์์ ํ ์ญ์ ๋จ | โ (๋ฑ๋ก ํด์ ๋จ) | โ (์กฐํ ๋ถ๊ฐ) | โ (์๋กญ๊ฒ ์ฌ๋ฑ๋กํด์ผ ํจ) |
๐ 2. ์๋ฒ ์ค์ ๋ฐฉ๋ฒ
โ 2-1. ์์กด์ฑ ์ถ๊ฐ
๐ build.gradle
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2024.0.0"
}
}
*๋ฒ์ ์ฐธ๊ณ
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies
โ 2-2. ์ ํ๋ฆฌ์ผ์ด์ ์ค์
๐ application.properties
spring.application.name=eureka
# Eureka ์๋ฒ ํฌํธ ์ค์
server.port=8761
# Eureka ์๋ฒ ์ค์
# ์ด ์๋ฒ๋ ๋ค๋ฅธ ์๋ฒ์ ๋ฑ๋กํ์ง ์์
eureka.client.registerWithEureka=false
# ์ด ์๋ฒ๋ ๋ค๋ฅธ ์๋ฒ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค์ง ์์
eureka.client.fetchRegistry=false
# ์๋ฒ ์๊ธฐ ๋ณดํธ ๋ชจ๋ ๋นํ์ฑํ
eureka.server.enableSelfPreservation=false
# ์ด ์ค์ ์ ํตํด ๊ธฐ๋ณธ UI๋ฅผ ํ์ฑํํ ์ ์์
management.endpoints.web.exposure.include=*
โ 2-3. @EnableEurekaServer ์ถ๊ฐ
๐ main class
package com.example.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
๐ 3. Client ์ค์ ๋ฐฉ๋ฒ
โ 3-1. ์์กด์ฑ ์ถ๊ฐ
๐ build.gradle
//eureka
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
โ 3-2. ์ ํ๋ฆฌ์ผ์ด์ ์ค์
๐ application.properties
spring.application.name=gateway
# Spring Cloud Gateway ์ค์
# ์๋ฒ ํฌํธ ์ค์
server.port=8080
# ๋ผ์ฐํธ ์ค์
# Eureka ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ์ ํตํฉ
# ๋ฑ๋ก๋ ์๋น์ค ์ด๋ฆ์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ธ์คํด์ค์ ๋ํด ๋ก๋ ๋ฐธ๋ฐ์ฑ์ ์ํ.
spring.cloud.gateway.routes[0].id=to_service1
spring.cloud.gateway.routes[0].uri=lb://SERVICE-1
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1/**
spring.cloud.gateway.routes[0].filters[0]=AddRequestHeader=X-Gateway-Header, Gateway-Value
# Eureka ์๋ฒ URL (Eureka์ ์ฐ๋ ์)
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
# Eureka ์๋น์ค ๋ฑ๋ก์ ํตํ ๋์ ๋ผ์ฐํ
ํ์ฑํ
spring.cloud.gateway.discovery.locator.enabled=true
# eureka server registry์ ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์์ ์ ์ ๋ณด๋ฅผ ๋ฑ๋กํ ์ง (๋ค๋ฅธ ์๋น์ค๋ค์ด name์ผ๋ก ์ ๊ทผ๊ฐ๋ฅ)
eureka.client.registerWithEureka=true
# registry์ ์๋ ์ ๋ณด(๋ฑ๋ก๋ ์๋น์ค ๋ชฉ๋ก)๋ค์ ๊ฐ์ ธ์ฌ์ง ์ฌ๋ถ
eureka.client.fetchRegistry=true
#Actuator ์๋ํฌ์ธํธ ํ์ฑํ -> ์ ํด๋ ๋๋๋ฐ ์ ๋ ์นด ์๋ฒ์์ ์กฐํํ๋๊ฒ ์์.
management.endpoints.web.exposure.include=*
โ 3-3. @EnableDiscoveryClient์ถ๊ฐ (์ต์ ๋ฒ์ ์์ ์๋ต ๊ฐ๋ฅ)
๐ main class
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
๐ 4. ์๋น์ค ํ์ธ
์ ํ๋ฆฌ์ผ์ด์ ์คํ ํ http://localhost:8761(์ ๋ ์นด ์๋ฒ ํฌํธ) ๋ก ์ ์ํ์ฌ ๋ฑ๋ก๋ ์๋น์คํ์ธ ๊ฐ๋ฅ.
- Instances ์์ ๋ฑ๋กํ application์ด ์กฐํ๋๋ค.
- status๋งํฌ ํด๋ฆญ ์ http://desktop-2lii5um:8080/actuator/info๋ก ์ด๋๋๋ค.
โ ์๋ฌ: Invalid host: lb://{service_name}
[139c33b5] There was an unexpected error (type=Internal Server Error, status=500).
Invalid host: lb://product_service
2025-01-08T13:03:38.745+09:00 INFO 14960 --- [gateway] [nio-8080-exec-5] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level. java.lang.IllegalArgumentException: Invalid character found in method name [0x160x030x010x000xf70x010x000x000xf30x030x030x850x020xcc00x8f>6\0xb60xd2e0xc20xb10xe80xa40xe60x86js0x8fl%,0xa90xd10x1aU0xd0,"0xbb0xcc ]. HTTP method names must be tokens
//…
[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@1dde45af}, order = 2147483647]] 2025-01-08T13:04:00.262+09:00 ERROR 14960 --- [gateway] [nio-8080-exec-6] a.w.r.e.AbstractErrorWebExceptionHandler : [6b9f950f] 500 Server Error for HTTP GET "/product/api/products/all" java.lang.IllegalStateException: Invalid host: lb://product_service at
๐ ํด๊ฒฐ ๋ฐฉ๋ฒ
1. ์๋น์ค ๋ช ๋์ port ์ง์ ์ค์
์ด๋ ๊ฒ ํ๋๊น ์ ์๋จ. -> ์ ๋ ์นด ๋ฌธ์ ์ธ ๊ฒ!!
spring.cloud.gateway.routes[1].uri=http://localhost:8083
# lb://product_service
2. ์๋น์ค ๋ช ์์
Eureka์ ๋ฑ๋กํ๋ ์๋น์ค์ _์์ผ๋ฉด ์๋๋ค๊ณ ํ๋ค. -๋ก ์์ ํ๋๊น ์ ์๋จ.
spring.application.name=product-service
'Backend > spring cloud (MSA)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก (0) | 2025.02.23 |
---|---|
[Kafka] ๊ณ ๊ธ ์ค์ (0) | 2025.02.23 |
Kafka๋? (0) | 2025.02.23 |
GateWay๋? (0) | 2025.02.16 |
Spring Cloud๋? (0) | 2025.02.16 |