
스프링 클라우드는 MSA 구현을 위한 도구 모음이라고 생각하면 된다.
개발자는 모놀리식 아키텍처를 구현하고 인프라가 MSA를 만들어주는 식이라고 한다.
Service discovery
MSA에서 Service discovery는 서비스의 위치를 알게 해준다.
(Service discovery is the process of automatically detecting devices and services on a network.)
강의에서는 Netflix의 Euerka 서비스를 이용한다.

유레카 서버 레지스트리에 서비스를 등록하고 client의 요청에 따라 찾아 쓰는 형식이다. REST기반이며 기본적인 LB 기능도 한다.
유레카 서버로 구동될 프로젝트를 만들고 서버 어노테이션을 붙인다. @EnableEurekaServer
포트는 8716으로 지정했다. 관리하는 용도이기때문에 서버에 등록하는 건 제외했다.
server.port=8761
spring.application.name=discovery-service
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
유레카 서버에 등록할 서비스 프로젝트를 만들고 클라이언트 어노테이션을 붙인다. @EnableEurekaClient
이때 포트는 딱히 지정해줘야할 필요가 없으므로 0으로 둬서 랜덤포트값을 가진다.
Gateway
앞서 실행한 Eureka 서버는 단지 등록된 서비스들을 관리하는 역할만 하게된다.
그러나 Frontend 개발자 에게 통일된 요청 정보가 필요하며 Load Balance와 유저 인증, 라우팅 등 통일된 로직을 실행할 곳이 필요해진다.
이를 위해 각 서비스들과 Client 사이에 Spring Cloud Gateway를 거치도록한다.
출처
만일 사용자가 직접 서비스들을 호출하게 된다면 하나의 작업에 여러 서비스들이 호출되어 성능과 효율이 떨어지게 된다.
게이트웨이도 마찬가지로 클라이언트 어노테이션으로 등록해준다. Gateway는 고정된 포트가 필요하다.
LoggingFilter 강의서 사용된 로깅필터는 Spring Cloud Gateway에서 지원하지 않는 커스텀 필터로 인터페이스를 상속받아 구현해야 한다.
GlobalFilter는 공통적으로 적용되는 필터로 마찬가지로 인터페이스를 상속받아야 한다.
OpenFeign
(Spring WebFlux기반 non-blocking i/o Feign Reactive도 있다)
Feign은 Http client binder이다.
@EnableFeignClients 어노테이션을 달면 @FeignClient 를 찾아 구현체를 만들어 준다. 이때 연결될 서비스의 이름을 달아주면 (@FeignClient(name = "MY-SERVICE2")해당 서비스에서 응답하게 된다.
Circuit Breaker
에러가 더 이상 전파되지 않도록 하는 장치를 이른다.

Software Load balancer
Eureka Client로 등록되어 좀 더 정교한 LB가 가능하다.
Spring Cloud Config
여기저기 흩어져 있는 application.properties나 yml들을 Config 서버가 모아서 관리한다.
git을 사용하여 전파한다. 그러나 config가 변경되면 각 마이크로서비스는 최신 값을 갖고 오기 위해 POST로 actuator/refresh를 해줘야 하므로, config server가 각 마이크로서비스의 주소를 모두 관리해야 하니 비효율적이다.
Spring Cloud Bus
그리하여 Spring Cloud Bus를 사용하게 된다.
RabbitMQ
초당 20개 이상의 메시지를 처리할 수 있는 능력을 가진 오픈소스 메시지 브로커이다.
Point To Point Message Model와 Pub/Sub Message Model 모두를 지원하지만 Point To Point Message Model 이 가장 적합하며 설정 정보와 같은 가볍고 적은 데이터를 처리하기에 적합하다.
Kafka
초당 10만개 이상이 메시지, 이벤트를 처리할 수 있는 능력을 가진 오픈소스 메시지 브로커이다.
Publisher가 Topic 에 메시지를 전달하고 해당 Topic을 구독하는 Subscriber 가 메시지를 가져다 사용하는 형태가 된다.

//Animal.java
public class Animal extends Thread {
private String howl;
public Animal() {}
public Animal(String howl) {
this.howl = howl;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(howl);
// sleep이 흐름을 방해하므로 오류가 날 수 있어서 예외 처리 필수
try {sleep(500);} catch (InterruptedException e) {;}
// 빈 중괄호는 예외처리가 끝났음을 알리거나
// 기본생성자에서 수정 사항이 없을 시
// 관용적으로 세미콜론을 남기기도 한다.
}
}
}
//Zoo.java
public class Zoo {
public static void main(String[] args) {
Animal dog = new Animal("woof");
Animal cat = new Animal("meow");
Animal duck = new Animal("quack");
dog.start();
cat.start();
try{dog.join();cat.join();}catch(InterruptedException e){;}
duck.start();
}
}
Thread의 join함수로 해당 객체의 일 처리가 끝난 후 다음 작업을 실행하도록 한다.