dnjscksdn98 / microservice-master-course

Microservices Master Course with Spring-Cloud

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

msa

Microservices Master Course with Spring

๐Ÿš€ Eureka ๊ฐœ์š”

์ •์˜

  • Client-side Service Discovery
  • Eureka๋Š” ์ฃผ์†Œ๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” AWS์™€ ๊ฐ™์€ Cloud ์‹œ์Šคํ…œ ํ™˜๊ฒฝ์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ ์„œ๋น„์Šค๋“ค์˜ IP / Port / Instance ID ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” REST ๊ธฐ๋ฐ˜์˜ ๋ฏธ๋“ค์›จ์–ด ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.
  • ์ฆ‰, Service Registry๋ฅผ ์ œ๊ณตํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

โœ” Eureka ์šฉ์–ด ์ •๋ฆฌ

Eureka ํ–‰๋™ ๊ด€๋ จ

  • Service Registration

    • ์„œ๋น„์Šค๊ฐ€ ์ž๊ธฐ ์ž์‹ ์˜ ์ •๋ณด๋ฅผ Eureka ์„œ๋ฒ„์— ๋“ฑ๋กํ•˜๋Š” ํ–‰๋™
  • Service Registry

    • ๋“ฑ๋ก๋œ ์„œ๋น„์Šค๋“ค์˜ ์ •๋ณด ๋ชฉ๋ก
  • Service Discovery

    • ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ ์ž ํ•˜๋Š” ๋Œ€์ƒ์˜ ์ •๋ณด๋ฅผ Service Registry๋ฅผ ํ†ตํ•ด ๋ฐœ๊ฒฌํ•˜๋Š” ๊ณผ์ •

Eureka ๊ตฌ์„ฑ ์š”์†Œ ๊ด€๋ จ

  • Eureka Client

    • ์„œ๋น„์Šค๋“ค์˜ ์œ„์น˜ ์ •๋ณด๋ฅผ ์•Œ์•„๋‚ด๊ธฐ ์œ„ํ•ด Eureka์— ์ •๋ณด๋ฅผ ์š”์ฒญํ•˜๋Š” ์„œ๋น„์Šค
  • Eureka Service

    • Eureka Client์— ์˜ํ•ด ๋ฐœ๊ฒฌ์˜ ๋Œ€์ƒ์ด ๋˜๋„๋ก Eureka์— ๋“ฑ๋ก์„ ์š”์ฒญํ•œ ์„œ๋น„์Šค
  • Eureka Server

    • Eureka Service๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ๋“ฑ๋ก(Service Registration)ํ•˜๋Š” ์„œ๋ฒ„์ด์ž, Eureka Client๊ฐ€ ๋“ฑ๋ก๋œ ์„œ๋น„์Šค ๋ชฉ๋ก(Service Registry)๋ฅผ ์š”์ฒญํ•˜๋Š” ์„œ๋ฒ„

โœ” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ

์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์˜ ๋„คํŠธ์›Œํฌ ์œ„์น˜๋ฅผ ์ฐพ๊ณ  ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋Š” ์‹œ์ž‘๋  ๋•Œ ์ž์‹ ์˜ ๋„คํŠธ์›Œํฌ ์ฃผ์†Œ๋ฅผ ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ(Service Registry) ์— ๋“ฑ๋กํ•˜๊ณ , ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋Š” ๊ฐ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์˜ ์ƒํƒœ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋“ฑ๋ก๋œ ์ธ์Šคํ„ด์Šค ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ณจ๋ผ์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ(Load Balancing) ์ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ธ์Šคํ„ด์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋“ฑ๋ก๋œ ์ •๋ณด๋Š” ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.

Netflix OSS๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ ํŒจํ„ด์˜ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค. Netflix Eureka๋Š” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋กœ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์˜ ๋“ฑ๋ก๊ณผ ๊ฐ€์šฉํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐพ๋Š” REST API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Netflix Ribbon์€ Eureka์™€ ๊ฐ™์ด ๋™์ž‘ํ•˜๋Š” IPC ํด๋ผ์ด์–ธํŠธ๋กœ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค ๊ฐ„ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์„ ํ•ด์ค๋‹ˆ๋‹ค.

โœ” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ

ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ๋Š” Service Client๊ฐ€ Service Registry์—์„œ ์ง์ ‘ ์„œ๋น„์Šค์˜ ์œ„์น˜๋ฅผ ์ฐพ์•„์„œ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ธ ๋ฐ˜๋ฉด์— ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ๋Š” ์ผ์ข…์˜ Proxy ์„œ๋ฒ„์ธ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋กœ ์š”์ฒญ์„ ๋จผ์ € ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋Š” Service Registry๋ฅผ ์กฐํšŒํ•ด์„œ ๊ฐ€์šฉํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐพ๊ณ  ๊ทธ ์ค‘ ์„ ํƒํ•ด์„œ ์š”์ฒญ์„ ๋ผ์šฐํŒ…ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. Service Registry์— ๋“ฑ๋ก๋˜๋Š” ๋ฐฉ์‹์€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

AWS Elastic Load Balancer(ELB) ๊ฐ€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋””์Šค์ปค๋ฒ„๋ฆฌ ํŒจํ„ด์˜ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค. ELB๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ธํ„ฐ๋„ท์—์„œ ๋“ค์–ด์˜ค๋Š” ์™ธ๋ถ€ ํŠธ๋ž˜ํ”ฝ์„ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ , VPC(Virtual Private Cloud) ์—์„œ ๋‚ด๋ถ€ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ์—์„œ DNS ์ด๋ฆ„์„ ์ด์šฉํ•ด ELB๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ELB๋Š” ๋“ฑ๋ก๋œ EC2(Elastic Compute Cloud) ์ธ์Šคํ„ด์Šค๋‚˜ ECS(EC2 Container Service) ์ปจํ…Œ์ด๋„ˆ ์‚ฌ์ด์—์„œ ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

โœ” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ

์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋Š” ๊ฐ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์˜ ๋„คํŠธ์›Œํฌ ์œ„์น˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ํ•ญ์ƒ ์ตœ์‹  ์ •๋ณด๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•˜๋ฉฐ ๊ณ ๊ฐ€์šฉ์„ฑ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€ํ‘œ์ ์ธ ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ธ Netflix Eureka๋Š” ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” REST ๊ธฐ๋ฐ˜ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋Š” POST ์š”์ฒญ์œผ๋กœ ์ž์‹ ์˜ ๋„คํŠธ์›Œํฌ ์œ„์น˜๋ฅผ ๋“ฑ๋กํ•˜๊ณ  30์ดˆ๋งˆ๋‹ค PUT ์š”์ฒญ์œผ๋กœ ์ž์‹ ์˜ ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. ๋“ฑ๋ก๋œ ์„œ๋น„์Šค ์ •๋ณด๋Š” DELETE ์š”์ฒญ์ด๋‚˜ ํƒ€์ž„ ์•„์›ƒ์œผ๋กœ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋“ฑ๋ก๋œ ์„œ๋น„์Šค ์ •๋ณด๋Š” GET ์š”์ฒญ์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ” ์„œ๋น„์Šค ๋“ฑ๋ก

๊ฐ ์„œ๋น„์Šค๋Š” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๊ฐ์ž์˜ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ํ•ด์ œํ•ด์•ผ ํ•˜๋Š”๋ฐ ์—ฌ๊ธฐ์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • ์…€ํ”„ ๋“ฑ๋ก ํŒจํ„ด (Self Registration Pattern): ์„œ๋น„์Šค ์Šค์Šค๋กœ ๋“ฑ๋ก์„ ๊ด€๋ฆฌ
  • ์จ๋“œ ํŒŒํ‹ฐ ๋“ฑ๋ก ํŒจํ„ด (3rd Party Registration Pattern): ์ œ 3์˜ ์‹œ์Šคํ…œ์—์„œ ๋“ฑ๋ก์„ ๊ด€๋ฆฌ

1) ์…€ํ”„ ๋“ฑ๋ก ํŒจํ„ด

๋“ฑ๋ก๊ณผ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์ฃผ์ฒด๊ฐ€ ์„œ๋น„์Šค์ธ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๊ฐ ์„œ๋น„์Šค๋Š” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์ž์‹ ์˜ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•˜๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด ์ฃผ๊ธฐ์ ์œผ๋กœ ์ž์‹ ์ด ์‚ด์•„ ์žˆ๋‹ค๋Š” ์‹ ํ˜ธ(Heartbeat)๋ฅผ ๊ณ„์† ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด ์ •๋ณด๊ฐ€ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ์˜ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ์„œ๋น„์Šค์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ๋ณด๊ณ  ๋“ฑ๋ก์ด ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„œ๋น„์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๋Š” ๋“ฑ๋ก์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

์•ž์„œ ์‚ดํŽด๋ณธ Eureka Client๊ฐ€ ์ด์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. Spring์—์„œ๋Š” @EnableEurekaClient ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2) ์จ๋“œ ํŒŒํ‹ฐ ๋“ฑ๋ก ํŒจํ„ด

์™ธ๋ถ€์—์„œ ์„œ๋น„์Šค ๋“ฑ๋ก์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ๋“ฑ๋ก์„ ๊ด€๋ฆฌํ•˜๋Š” ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ผ(Service Registrar) ๋ฅผ ๋”ฐ๋กœ ๋‘๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ผ๋Š” ๊ฐ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์˜ ๋ณ€ํ™”๋ฅผ ํด๋ง(Polling)์ด๋‚˜ ์ด๋ฒคํŠธ ๊ตฌ๋…์œผ๋กœ ๊ฐ์ง€ํ•ด์„œ ์„œ๋น„์Šค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๊ณ„์† ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

๐Ÿš€ Eureka Server ํ™˜๊ฒฝ ๊ตฌ์ถ•

1) ์˜์กด์„ฑ ์„ค์ •

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2) @EnableEurekaServer ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}

3) ํ”„๋กœํผํ‹ฐ ์„ค์ •(Config Server ๋‚ด์˜ eureka-server.yml)

  • registerWithEureka: false -> Eureka Service์— ์ž์‹ ์„ ๋“ฑ๋กํ•˜์ง€ ์•Š๋Š”๋‹ค
  • fetchRegistry: false -> Registry ์ •๋ณด๋ฅผ ๋กœ์ปฌ์— ์บ์‹ฑํ•˜์ง€ ์•Š๋Š”๋‹ค
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://localhost:8010/eureka/

๐ŸŒŸ Eureka Client ํ™˜๊ฒฝ ๊ตฌ์ถ•

1) ์˜์กด์„ฑ ์„ค์ •

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2) @EnableEurekaClient ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

@SpringBootApplication
@EnableEurekaClient
public class LicenseServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(LicenseServiceApplication.class, args);
	}
}

3) ํ”„๋กœํผํ‹ฐ ์„ค์ •(Config Server ๋‚ด์˜ license-service.yml)

  • preferIpAddress: true -> ์„œ๋น„์Šค์˜ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์ด ์•„๋‹Œ IP ์ฃผ์†Œ๋ฅผ Eureka์— ๋“ฑ๋กํ•˜๋„๋ก ์ง€์ •

โœ” IP ์ฃผ์†Œ๋ฅผ ์„ ํ˜ธํ•˜๋Š” ์ด์œ 

๊ธฐ๋ณธ์ ์œผ๋กœ Eureka๋Š” ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์œผ๋กœ ์ ‘์†ํ•˜๋Š” ์„œ๋น„์Šค๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ DNS๊ฐ€ ์ง€์›๋œ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์„ ํ• ๋‹นํ•˜๋Š” ์„œ๋ฒ„ ๊ธฐ๋ฐ˜ ํ™˜๊ฒฝ์—์„œ ์ž˜ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋ฐ˜์˜ ํ™˜๊ฒฝ์—์„œ๋Š” DNS ์—”ํŠธ๋ฆฌ๊ฐ€ ์—†๋Š” ์ž„์˜๋กœ ์ƒ์„ฑ๋œ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์„ ๋ถ€์—ฌ๋ฐ›์•„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ๊ฐ’์„ true๋กœ ์„ค์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํ•ด๋‹น ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ DNS ์—”ํŠธ๋ฆฌ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์˜ ์œ„์น˜๋ฅผ ์ •์ƒ์ ์œผ๋กœ ์–ป์ง€ ๋ชปํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

eureka:
  instance:
    preferIpAddress: true
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://localhost:8010/eureka/

๐Ÿš€ Spring Cloud Config Server๋ž€?

Spring Cloud Config Server๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ๋กœ ๋งŒ๋“  REST ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์—์„œ ํ™˜๊ฒฝ์„ค์ •์„ ์™ธ๋ถ€๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค. Config Server๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ํ™˜๊ฒฝ(๊ฐœ๋ฐœ, ํ…Œ์ŠคํŠธ, ํ”„๋กœ๋•์…˜ ๋“ฑ)์— ๋Œ€ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์˜ ์†์„ฑ์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์žฅ์ 

  • ์„ค์ • ๊ด€๋ฆฌ์˜ ์šฉ์ด์„ฑ
  • ์šด์˜์ค‘์— ์„œ๋ฒ„ ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌ๋ฅผ ๋‹ค์‹œ ํ•  ํ•„์š” ์—†์ด ํ™˜๊ฒฝ์„ค์ • ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

๊ธฐ๋Šฅ

Spring Cloud Config Server

  • ํ™˜๊ฒฝ์„ค์ •(name-value pair, YAML ํŒŒ์ผ)์„ ์œ„ํ•œ HTTP, ๋ฆฌ์†Œ์Šค ๊ธฐ๋ฐ˜ API
  • ์†์„ฑ ๊ฐ’ ์•”ํ˜ธํ™” ๋ฐ ์•”ํ˜ธ ํ•ด๋… (๋Œ€์นญ ๋˜๋Š” ๋น„๋Œ€์นญ)
  • @EnableConfigServer ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ Spring Boot ์–ดํ”Œ์ผ€์ด์…˜์— ์ ์šฉ

Config Client(for Spring Boot ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜)

  • Config Server์— ๋ถ™์–ด ์›๊ฒฉ ์†์„ฑ ์†Œ์Šค๋กœ Spring ํ™˜๊ฒฝ ์ดˆ๊ธฐํ™”
  • ์†์„ฑ ๊ฐ’ ์•”ํ˜ธํ™” ๋ฐ ์•”ํ˜ธ ํ•ด๋… (๋Œ€์นญ ๋˜๋Š” ๋น„๋Œ€์นญ)

Config Server ๊ตฌ์กฐ

์˜์กด์„ฑ ์„ค์ •

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-config-server</artifactId>
</dependency>

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ ์„ค์ •(application.yml)

spring:
  application:
    name: {application.name}

  profiles:
    active: git

  cloud:
    config:
      server:
        git:
          uri: {remote.property.source.uri}
          username: {username}
          password: {password}

@EnableConfigServer ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

@SpringBootApplication
@EnableConfigServer
public class PhotoAppApiConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(PhotoAppApiConfigServerApplication.class, args);
	}
}

Spring Cloud Config Client ๊ตฌ์กฐ

์˜์กด์„ฑ ์„ค์ •

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Remote Git Repository์— ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ ์ƒ์„ฑ

  • ์šฐ์„ ์ˆœ์œ„: {application.name}-{profile}.yml > {application.name}.yml > application.yml

๋ถ€ํŠธ์ŠคํŠธ๋ž˜ํ•‘ ์„ค์ •(bootstrap.yml)

spring:
  application:
    name: {application.name}

  profiles:
    active: {profile}

  cloud:
    config:
      uri: {config.server.uri}
  • ์ด๋•Œ, spring.application.name์€ ์›๊ฒฉ ์ €์žฅ์†Œ์— ์žˆ๋Š” ํŒŒ์ผ๋ช…์ด๋ž‘ ๋™์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์›๊ฒฉ ์ €์žฅ์†Œ์— ๋””๋ ‰ํ„ฐ๋ฆฌ๋ณ„๋กœ ๊ด€๋ฆฌ์ค‘์ด๋ผ๋ฉด spring.cloud.config.server.git.searchPaths ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๐Ÿš€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ๊ฐ„์˜ ํ†ต์‹ 

  • ๋ชจ๋†€๋ฆฌ์‹ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ๋‹ค๋ฅธ ๋ฉ”์†Œ๋“œ๋‚˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์—์„œ๋Š” ์„œ๋น„์Šค ๋‹จ์œ„๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋น„์Šค ๊ฐ„์˜ ํ†ต์‹ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ํ†ต์‹ ์„ **ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹ (Inter-Process Communication)**์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

ํ†ต์‹  ๋ฐฉ์‹

  • ํ†ต์‹  ๋ฐฉ์‹์€ ๋จผ์ € ํ˜ธ์ถœํ•˜๋Š” ์ชฝ๊ณผ ํ˜ธ์ถœ๋‹นํ•˜๋Š” ์ชฝ์˜ ์ˆ˜๋กœ ๊ตฌ๋ถ„ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•˜๋‚˜์˜ ์š”์ฒญ์ด ํ•˜๋‚˜์˜ ์„œ๋น„์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ผ๋Œ€์ผ(One-to-One)

  • ํ•˜๋‚˜์˜ ์š”์ฒญ์ด ์—ฌ๋Ÿฌ ์„œ๋น„์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์ผ๋Œ€๋‹ค(One-to-Many)

  • ๊ทธ๋ฆฌ๊ณ  ๋™๊ธฐ(Synchronous)์™€ ๋น„๋™๊ธฐ(Asynchronous)๋กœ๋„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋™๊ธฐ ๋ฐฉ์‹์€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ดํ›„ ๋™์ž‘์€ ๋ฉˆ์ถ˜ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‘๋‹ต์„ ๋ฐ›์€ ํ›„์— ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ˜๋Œ€๋กœ ๋น„๋™๊ธฐ ๋ฐฉ์‹์€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

image

  • 1) ์š”์ฒญ / ์‘๋‹ต: ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

  • 2) ์•Œ๋ฆผ: ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ์˜ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  • 3) ์š”์ฒญ / ๋น„๋™๊ธฐ ์‘๋‹ต: ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ๋น„๋™๊ธฐ๋กœ ์‘๋‹ต์ด ์˜ต๋‹ˆ๋‹ค.

  • 4) ํผ๋ธ”๋ฆฌ์‹œ / ๊ตฌ๋…: ๋“ฑ๋ก๋œ ์„œ๋น„์Šค๋“ค์— ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์š”์ฒญ์„ ๋ฐ›์€ ์„œ๋น„์Šค๋“ค์€ ๊ฐ์ž ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • 5) ํผ๋ธ”๋ฆฌ์‹œ / ๋น„๋™๊ธฐ ์‘๋‹ต: ์œ„์™€ ๊ฐ™์ง€๋งŒ ๋น„๋™๊ธฐ ํ˜•ํƒœ๋กœ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋”ฐ๋ผ์„œ ํ•˜๋‚˜์˜ ๋ฐฉ์‹๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜๊ธฐ๋„ ํ•˜๊ณ , ์—ฌ๋Ÿฌ ๋ฐฉ์‹์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ํƒ์‹œ ํ˜ธ์ถœ ์„œ๋น„์Šค๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    1. ์Šน๊ฐ์ด ๋ชจ๋ฐ”์ผ๋กœ ํ”ฝ์—…์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ์ด ์š”์ฒญ์€ ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค (์•Œ๋ฆผ)
    1. ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋Š” ์Šน๊ฐ ๊ด€๋ฆฌ ์„œ๋น„์Šค์—์„œ ์Šน๊ฐ ์ •๋ณด๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค (์š”์ฒญ/์‘๋‹ต)
    1. ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋Š” ํ•ด๋‹น ์—ฌํ–‰์„ ๋””์ŠคํŒจ์ฒ˜์™€ ๊ฐ€๊นŒ์šด ํƒ์‹œ๊ธฐ์‚ฌ์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค (ํผ๋ธ”๋ฆฌ์‹œ/๊ตฌ๋…)

๋™๊ธฐ ๋ฐฉ์‹ - REST

  • ํƒ์‹œ ํ˜ธ์ถœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์Šน๊ฐ์ด ํƒ์‹œ๋ฅผ ๋ถ€๋ฅผ ๋•Œ REST API๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, POST ๋ฐฉ์‹์œผ๋กœ /trips ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค์—์„œ ์Šน๊ฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด, ์Šน๊ฐ ๊ด€๋ฆฌ ์„œ๋น„์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” REST API๋ฅผ ์‚ฌ์šฉํ•ด์„œ GET ๋ฐฉ์‹์œผ๋กœ /passengers/{passengerId} ๋กœ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

  • ๊ทธ๋Ÿผ ์Šน๊ฐ ID๋กœ ์Šน๊ฐ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด์„œ ํ•ด๋‹น ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์—ฌํ–‰ ์ •๋ณด๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • REST๋Š” ๋™๊ธฐ ๋ฐฉ์‹์ด๋ฏ€๋กœ ์š”์ฒญํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” ์‘๋‹ต์„ ๋ฐ›์€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ๊ทธ๋ฆฌ๊ณ  ํ•ญ์ƒ ์ผ๋Œ€์ผ ํ†ต์‹  ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ๋ฐฉ์‹ - ๋ฉ”์‹œ์ง•

  • ๋น„๋™๊ธฐ ๋ฐฉ์‹์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋†“๊ณ  ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ด ๋ฉ”์‹œ์ง€๋Š” Header์™€ Body๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ  Channel์„ ํ†ตํ•ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€๋Š” ํ•œ ๊ณณ์—์„œ๋งŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ณ (์ผ๋Œ€์ผ), ํผ๋ธ”๋ฆฌ์‹œ/๊ตฌ๋… ๋ชจ๋ธ์„ ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๊ณณ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ผ๋Œ€๋‹ค).
  • ์ฆ‰, ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ฒ ๋‹ค๊ณ  ๊ตฌ๋…ํ•ด๋†“์€ ์„œ๋น„์Šค์—๊ฒŒ ๋ชจ๋‘ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์ด๋Ÿฌํ•œ ๋ฉ”์‹œ์ง• ๋ฐฉ์‹์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋น„์Šค ์‚ฌ์ด์˜ ์˜์กด๋„๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
  • ๋™๊ธฐ ๋ฐฉ์‹์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋น„์Šค๊ฐ€ ์„œ๋กœ๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ณ  ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๊ตฌ์กฐ์ด์ง€๋งŒ,
  • ๋ฉ”์‹œ์ง• ๋ฐฉ์‹์€ ๊ทธ ์‚ฌ์ด์— ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์ด ๋“ค์–ด๊ฐ€์„œ ๊ฐ„์ ‘์ ์œผ๋กœ ํ†ต์‹ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์ผ๋Œ€์ผ ํ†ต์‹  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ๋Œ€๋‹ค ํ†ต์‹ ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ๋„ ์žฅ์ ์ž…๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋Š” ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์€ AMQP์ž…๋‹ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์˜คํ”ˆ์†Œ์Šค ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์€ ๋Œ€ํ‘œ์ ์œผ๋กœ RabbitMQ์™€ Apache Kafka๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿš€ ์„œ๋น„์Šค ๋””์Šค์ปค๋ฒ„๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ์„œ๋น„์Šค ๊ฒ€์ƒ‰

  • ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋Š” ์–ด๋–ป๊ฒŒ ์Šน๊ฐ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋ฅผ ์•Œ๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ผ๊นŒ์š”?
  • ์ด๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ ์€ Eureka Discovery Service์ž…๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๊ฐ€ ์‹คํ–‰์ด ๋ ๋•Œ Eureka Discovery Service๋กœ ๋“ฑ๋ก์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ Eureka๋Š” ํ˜„์žฌ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๋“ค์˜ ์ฃผ์†Œ์™€ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์—ฌํ–‰ ๊ด€๋ฆฌ ์„œ๋น„์Šค๋Š” Eureka๋ฅผ ํ†ตํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผํ•  ์˜ฌ๋ฐ”๋ฅธ ์ฃผ์†Œ์™€ ํฌํŠธ๋ฒˆํ˜ธ๋ฅผ ์•Œ๊ฒŒ ๋˜์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

โœ” RestTemplate์„ ํ†ตํ•œ ํ†ต์‹ 

RestTemplate ๋นˆ ๋“ฑ๋ก

  • @LoadBalanced : ์Šคํ”„๋ง ํด๋ผ์šฐ๋“œ๊ฐ€ Ribbon์„ ์ง€์›ํ•˜๋Š” RestTemplate ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์ง€์ •
@SpringBootApplication
@EnableEurekaClient
public class PhotoAppApiUsersApplication {

	public static void main(String[] args) {
		SpringApplication.run(PhotoAppApiUsersApplication.class, args);
	}

	@Bean
	@LoadBalanced
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}

RestTemplate Client ์ƒ์„ฑ

  • restTemplate.exchange({url}, {HTTP Method}, {HTTP Entity(Header/Body)}, {response type}, {parameter})

  • RestTemplate ํ˜ธ์ถœ์—์„œ ์„œ๋น„์Šค์˜ ๋ฌผ๋ฆฌ์  ์œ„์น˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ํ˜ธ์ถœํ•˜๋ ค๋Š” ์„œ๋น„์Šค์˜ ์œ ๋ ˆ์นด ์„œ๋น„์Šค ID๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(spring.application.name).

  • RestTemplate์ด Eurekaํ•œํ…Œ organization-service์— ๋Œ€ํ•œ ๋ชจ๋“  ์ฃผ์†Œ๋“ค์„ ๋จผ์ € ๋ฌผ์–ด๋ณด๊ณ , ๋ฐ›์€ ์ฃผ์†Œ๋“ค์„ ๊ฐ€์ง€๊ณ  ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ(๋ผ์šด๋“œ ๋กœ๋นˆ ๋ฐฉ์‹)์„ ํ†ตํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

@Component
public class OrganizationRestTemplateClient {

    @Autowired
    private RestTemplate restTemplate;

    public Organization getOrganization(String organizationId) {
        ResponseEntity<Organization> restExchange =
                restTemplate.exchange(
                        "http://organization-service/v1/organizations/{organizationId}",
                        HttpMethod.GET,
                        null,
                        Organization.class,
                        organizationId
                );

        return restExchange.getBody();
    }
}

โœ” Feign Client๋ฅผ ํ†ตํ•œ ํ†ต์‹ 

  • REST ๊ธฐ๋ฐ˜ ์„œ๋น„์Šค ํ˜ธ์ถœ์„ ์ถ”์ƒํ™”ํ•œ Spring Cloud Netflix ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ์„ ์–ธ์  ๋ฐฉ์‹(Declarative REST Client)
  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ ์ธก ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ
  • Spring์ด ๋Ÿฐํƒ€์ž„์— ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณต

์˜์กด์„ฑ ์„ค์ •

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

@EnableFeignClients ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class PhotoAppApiUsersApplication {

	public static void main(String[] args) {
		SpringApplication.run(PhotoAppApiUsersApplication.class, args);
	}
}

Feign Client ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ

  • @FeignClient(name = "{service.name}") -> ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋Œ€ํ‘œํ•  ์„œ๋น„์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง€์ •
@FeignClient(name = "organization-service", path = "v1/organizations/")
public interface OrganizationFeignClient {

    @GetMapping(path = "{organizationId}", produces = MediaType.APPLICATION_JSON_VALUE)
    Organization getOrganization(@PathVariable("organizationId") String organizationId);

}

Feign Client์— ๋Œ€ํ•œ ๋กœ๊น… ์„ค์ •

  • ํŒจํ‚ค์ง€ ์ „์ฒด ํ™œ์„ฑํ™”
logging:
  level:
    com:
      alexcode:
        photoapp:
          api:
            users:
              PhotoAppApiUsers:
                feign: DEBUG
  • ํŠน์ • ํด๋ผ์ด์–ธํŠธ๋งŒ ํ™œ์„ฑํ™”
logging:
  level:
    com:
      alexcode:
        photoapp:
          api:
            users:
              PhotoAppApiUsers:
                feign:
                  AlbumServiceClient: DEBUG
  • ๋กœ๊น… ๋ ˆ๋ฒจ์— ๋Œ€ํ•œ ๋นˆ ์ƒ์„ฑ
@Configuration
public class FeignClientConfig {

	@Bean
	Logger.Level feignLoggerLevel() {
		return Logger.Level.FULL;
	}
}
  • NONE: ๋กœ๊น… ์—†์Œ, ๋””ํดํŠธ๊ฐ’
  • BASIC: ์š”์ฒญ ํ•จ์ˆ˜, URL, ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋งŒ์„ ๋กœ๊น…
  • HEADERS: BASIC์—๋‹ค๊ฐ€ ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ Header๊นŒ์ง€ ๋กœ๊น…
  • FULL: ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ Body, Header ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์™ธ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊นŒ์ง€ ๋กœ๊น…

References

About

Microservices Master Course with Spring-Cloud


Languages

Language:Java 97.9%Language:Dockerfile 2.1%