๐ MSA(MicroService Architecture)๋?
์ฌ๋ฌ ๊ฐ์ ์์ ์๋น์ค๋ก ๊ตฌ์ฑ๋์ด ๊ฐ ์๋น์ค๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฐ๋๊ณ ๋ฐฐํฌ๋๋ ๊ตฌ์กฐ
→ ์ ์ฒด ์์คํ ์ด ๋ถ์ฐ๋์ด ์์ด ๊ฐ๋ฐ, ๋ฐฐํฌ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฅํ๋ฉฐ ํ์ฅ์ฑ๊ณผ ์ ์ง ๊ด๋ฆฌ๊ฐ ์ฉ์ดํ๋ค
์ฐ๋ฆฌ ํ๋ก์ ํธ์์๋ ํ์, ๊ฐ์ ๋ถ์ - ์ฃผ๋ฅ ์ถ์ฒ, ์ฃผ๋ฅ ๋ฆฌ๋ทฐ ๊ด๋ฆฌ ์ด๋ ๊ฒ ์ด 3๊ฐ์ง๋ก ๊ตฌ๋ถํ์๋ค
+ ๊ฐ ์๋น์ค๋ง๋ค ๋ ๋ฆฝ์ ์ธ DB!
๐ Netflix OSS Eureka Server
โ Spring Cloud Netflix
์คํ๋ง ๋ถํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ ํตํฉ ํ๊ฒฝ ๊ตฌ์ฑ์ ์ง์ํ๋ Netflix์ OSS ์๋น์ค
โ Eureka
Netflix OSS ์๋น์ค ์ค ํ๋๋ก ๊ฐ๊ฐ์ ์๋น์ค ์ธ์คํด์ค๋ค์ด ๋์ ์ผ๋ก ํ์ฅ, ์ถ์ ๋๋๋ผ๋ ์ธ์คํด์ค์ ์ํ๋ฅผ ํ๋์ ์๋น์ค๋ก ๊ด๋ฆฌํ ์ ์๋ ์๋น์ค
์ต์ด์๋ ๋ชจ๋ ์๋น์ค๊ฐ Spring Cloud์ ์ํด์ ๊ด๋ฆฌ๋์์ง๋ง ํ์ฌ๋ ๋ช๋ช ๊ธฐ์ ๋ค์ ์ฌ๊ตฌ์ฑ ํน์ ๋ฐ์ ์ํค๊ฑฐ๋ ๋ ๋ฆฝ์ ์ธ ์๋น์ค๋ก ์งํ์์ผ ๊ธฐ์กด์ ์๋น์ค๋ค์ Maintenance ๋ชจ๋๋ก ๋ค์ด๊ฐ ๊ฒ๋ค์ด ์กด์ฌํ๋ค
* Maintenance : ๋ชจ๋์ ์ ์ง ๋ณด์ ๋ชจ๋๋ก ์ ํํ๋ฉด Spring-Cloud ํ์ด ๋ ์ด์ ๋ชจ๋์ ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ์ง ์๊ฒ ๋๋ค
<๊ตฌ์ฑ>
Eureka๋ Eureka Server์ Eureka Client๋ก ๊ตฌ์ฑ๋๋ค
- Eureka Server : Eureka Client์ ํด๋นํ๋ ๋ง์ดํฌ๋ก์๋น์ค๋ค์ ์ํ ์ ๋ณด๊ฐ ๋ฑ๋ก๋์ด ์๋ ๋ ์ง์คํธ๋ฆฌ๋ฅผ ๊ฐ๋๋ค
- Eureka Client : ์๋น์ค๊ฐ ์์๋ ๋ Eureka Server์ ์์ ์ ์ ๋ณด๋ฅผ ๋ฑ๋กํ๋ค. ๋ฑ๋ก๋ ํ์๋ 30์ด๋ง๋ค ๋ ์ง์คํธ๋ฆฌ์ ping์ ์ ์กํ์ฌ ์์ ์ด ๊ฐ์ฉ ์ํ์์ ์๋ฆฌ๋๋ฐ ์ผ์ ํ์ ์ด์ ping์ด ํ์ธ๋์ง ์์ผ๋ฉด Eureka Server์์ ํด๋น ์๋น์ค๋ฅผ ๋ ์ง์คํธ๋ฆฌ์์ ์ ์ธ์ํจ๋ค
<ํ๋ก์ ํธ์ ์ ์ฉํ๊ธฐ>
1. Service Discovery Sever ํ๋ก์ ํธ ์์ฑ
์ด๋, ์๋์ ๊ฐ์ด dependency ์ฐฝ์์ Eureka Server๋ฅผ ์ถ๊ฐํ๋ค
2. eureka ์๋ฒ์ application.yml ํ์ผ ์ถ๊ฐ
spring:
application:
name: eureka
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
serviceUrl:
defaultZone: http://localhost:8761/eureka/
- register-with-eureka : ์ ๋ ์นด ์๋น์ค ๋ฑ๋ก ์ฌ๋ถ
- fetch-registry : ๋ ์ง์คํธ๋ฆฌ ์ ๋ณด ์บ์ฑ ์ฌ๋ถ
3. @EnableEurekaServer ์ด๋ ธํ ์ด์ ์ถ๊ฐ
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
4. ๊ฒ์ดํธ์จ์ด ์๋น์ค ์์ฑ
์ด๋, ์๋์ ๊ฐ์ด dependency ์ฐฝ์์ Gateway๋ฅผ ์ถ๊ฐํ๋ค + Eureka Discovery Client๋ ์ถ๊ฐ
5. ๊ฒ์ดํธ์จ์ด ์๋น์ค ํ๋ก์ ํธ์ application.yml ์์ฑ
eureka:
instance:
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
- prefer-ip-address : ์ ๋ ์นด ์๋น์ค ๋ฑ๋ก ์ฌ๋ถ
- register-with-eureka : ๋ ์ง์คํธ๋ฆฌ์ ์์ ์ ๋ฑ๋กํ ๊ฒ์ธ์ง์ ๋ํ ์ฌ๋ถ
- fetch-registry : ๋ ์ง์คํธ๋ฆฌ์ ์๋ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ์ธ์ง์ ๋ํ ์ฌ๋ถ
6. ๊ฒ์ดํธ์จ์ด ์๋น์ค ํ๋ก์ ํธ์๋ ๋์ผํ๊ฒ @EnableEurekaServer ์ด๋ ธํ ์ด์ ์ถ๊ฐํด์ผ ํ๋ค
7. Eureka Server์ Service ๋ฑ๋ก
Service ํ๋ก์ ํธ ์์ฑ ํ Eureka Discovery Client ์ถ๊ฐ
(Spring Web๋ ์ถ๊ฐํด์ผ ํ๋ค)
8. ์๋น์ค ํ๋ก์ ํธ์ application.yml ํ์ผ ์์ฑ
eureka:
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 30
client:
registry-fetch-interval-seconds: 30
disable-delta: true
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
- registry-fetch-interval-seconds : ๋ ์ง์คํธ๋ฆฌ ์ ๋ณด ์บ์ฑ ์ฌ๋ถ
- disable-delta : ์ ๋ ์นด ์๋ฒ์๊ฒ ์๋น์ค ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋ ๋ณ๊ฒฝ๋ ๋ด์ฉ๋ง ๊ฐ์ง๊ณ ์ค๋ ๊ฒ์ ๋ํ ์ฌ๋ถ
9. ์๋น์ค ํ๋ก์ ํธ์๋ ๋์ผํ๊ฒ @EnableEurekaServer ์ด๋ ธํ ์ด์ ์ถ๊ฐํด์ผ ํ๋ค
๐ข ์์ฒญ ๋ณด๋ด๊ธฐ
http://localhost:9000/auth/login์ผ๋ก ์์ฒญํ๋ฉด ๊ฒ์ดํธ์จ์ด ์๋น์ค๊ฐ ์ด๋ฅผ auth ์๋น์ค์ /login ๊ฒฝ๋ก๋ก ๋ผ์ฐํ ํ๋ค
auth ์๋น์ค์ ๊ฒฝ์ฐ ๊ฒ์ดํธ์จ์ด์์ ํํฐ๋ฅผ ์ถ๊ฐํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ธ์ฆ์ฒ๋ฆฌ๋ ์งํ๋์ง ์๋๋ค
๐ ํํฐ ์ถ๊ฐํ๊ธฐ
API Gateway๋ API ์๋ฒ ์๋จ์์ ๋ชจ๋ API ์๋ฒ๋ค์ ์๋ํฌ์ธํธ๋ฅผ ๋จ์ผํ ํด์ฃผ๋ ๋ ๋ค๋ฅธ ์๋ฒ์ด๋ค
API์ ๋ํ ์ธ์ฆ๊ณผ ์ธ๊ฐ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ๋ฉ์์ง์ ๋ด์ฉ์ ๋ฐ๋ผ ์ ํ๋ฆฌ์ผ์ด์ ๋ด๋ถ์ ์๋ ๋ง์ดํฌ๋ก ์๋น์ค๋ก ๋ผ์ฐํ ํ๋ ์ญํ ์ ํ๋ค
→ ์ด๋ Filter ๊ธฐ๋ฅ์ ํตํด ์กฐ๊ฑด์ ๋ถ๊ธฐํ๋ค
gateway:
routes:
- id: auth
uri: http://localhost:8090/
predicates:
- Path=/auth/**
- id: analyze
uri: http://localhost:8091/
predicates:
- Path=/analyze/**
filters:
- name: AuthorizationHeaderFilter
๋ผ์ฐํ ์ค์ ์๋์ filters๋ฅผ ์ถ๊ฐํ์ฌ ์ผ๋ฐ ์ปค์คํ ํํฐ(AuthorizationHeaderFilter)๋ฅผ ์ ์ฉํ์๋ค
auth ์๋น์ค์ ๊ฒฝ์ฐ์๋ ์ธ์ฆ ์์ฒญ์ ์งํํ์ง ์์ผ๋ฉฐ analyze ์๋น์ค์ ๋ํด ์ธ์ฆ์ ์งํํ๊ฒ ๋๋ค
@Component
@Slf4j
public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<AuthorizationHeaderFilter.Config> {
public AuthorizationHeaderFilter() {
super(Config.class);
}
public static class Config {
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
};
}
}
AuthorizationHeaderFilter์๋ jwt ํ ํฐ์ ๊ฒ์ฆํ๋ ์ฝ๋๋ฅผ ๊ตฌํํ์๋ค
๐ ์๋น์ค ๊ฐ ํต์ ์ ์ด๋ป๊ฒ?
์ฐ๋ฆฌ ํ๋ก์ ํธ์์๋ ํ์์ด ์ฃผ๋ฅ ๋ฆฌ๋ทฐ๋ฅผ ๋จ๊ธธ ๋ ํด๋น ํ์์ ์ ๋ณด๊ฐ ํ์ํ๋ฐ ์ฃผ๋ฅ ๋ฆฌ๋ทฐ ์๋น์ค์ ํ์ ์๋น์ค๊ฐ ๋ถ๋ฆฌ๋์ด ์๊ธฐ ๋๋ฌธ์ MSA๊ฐ์ ํต์ ์ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ค
1๏ธโฃ RestTemplate
HTTP ํต์ ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค๋ฅธ MSA์ ์์ฒญ์ ๋ ๋ฆฌ๊ณ ์ป์ด์จ ์๋ต์ ํ์ฉํ๋ ๋ฐฉ์์ด๋ค
2๏ธโฃ FeignClient
Feign์ ์๋น์ค ๊ฐ ํต์ ์ ๊ตฌํํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค
๋ด๋ถ์ ์ผ๋ก HTTP ํต์ ์ฝ๋๋ฅผ ์๋์ผ๋ก ์์ฑํด์ค๋ค
์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ์ฌ RESTful ์๋น์ค ๊ฐ์ ํต์ ์ ์ง์ ์ ์ํ์ง ์๊ณ ์ธํฐํ์ด์ค ํํ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค
(์ฐ๋ฆฌ ํ๋ก์ ํธ์์๋ FeginClient๋ฅผ ์ฌ์ฉํ์๋ค)
@FeignClient(name = "auth-service", url = "http://sunjoo-server-auth-spring-1:8090")
public interface UserClient {
@GetMapping("/auth/userinfo")
UserInfoResponse getUserInfo(@RequestHeader("Authorization") String token);
}
๋ฐ๋ก UserClinet ํด๋์ค ์์ฑ ํ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค
name์๋ ๋ค๋ฅธ MSA์ ์ด๋ฆ์ ์ ์ด์ฃผ๊ณ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ๋ ๊ฒ๊ณผ ์ ์ฌํ๊ฒ GET์ผ๋ก auth-service์ /auth/userinfo๋ก ์์ฒญ์ ์ ์ํ๊ณ ์์ฒญ ํค๋์ ํ ํฐ์ ์ถ๊ฐํด์ฃผ์๋ค
'๐ Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CORS] CORS๋? CORS ์๋ฌ ํด๊ฒฐ! (0) | 2024.06.30 |
---|---|
[Spring boot] (์๋ธ๋ฆฌํ์ ํด๋ก ์ฝ๋ฉ) + MySQL, ํ์ ๊ฐ์ ๊ตฌํ(2) (0) | 2023.07.15 |
[Spring boot] (์๋ธ๋ฆฌํ์ ํด๋ก ์ฝ๋ฉ) + MySQL, ํ์ ๊ฐ์ ๊ตฌํ(1) (0) | 2023.07.13 |