[Spring Cloud] - 7. Hystrix๋ฅผ ์ด์ฉํ Circuit Breaker (๊ธฐ๋ณธํธ)
์ง๋ ํฌ์คํธ์ ์ด์ด์ Spring Cloud์์ Circuit Breaker๋ฅผ ๊ตฌํํ ์ ์๋ ์ฒซ ๋ฒ์งธ ํํธ๋ฅผ ๋ค์ด๊ฐ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Hystrix
Hystrix๋ Spring Cloud ์คํ์์ ์ ๊ณตํ๋ Circuit Breaker ์ค ํ๋์ ๋๋ค. Netflix์์ ๊ฐ๋ฐํ์ผ๋ฉฐ ํ์ฌ๋ Spring Cloud์ ํ์ค Circuit Breaker๋ก ์๋ฆฌ ์ก๊ณ ์์ฃ .
๊ธฐ๋ณธ์ ์ผ๋ก Hystrix๋ ์์ ๊ฐ์ ํํ๋ก ๋์ํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ํน์ ๋ชจ๋ฐ์ผ์์ ์ด๋ค API ์์ฒญ์ด ๋ค์ด์์ ๊ฒฝ์ฐ, ํด๋น ์๋น์ค์ ์๋ํฌ์ธํธ๊ฐ ํธ์ถ๋๋๋ฐ, ์ด ๋ ์๋น์ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฑฐ๋ ์๋ต์ด ์์ ๊ฒฝ์ฐ, ์ดํ ์ด์ฉ์์๊ฒ ์ฅ์ ๊ฐ ์ ํ๋์ง ์๊ณ , ๋ฏธ๋ฆฌ ์ ์๋ ์ค๋ฅ๋ฅผ ๋ธ๋ผ์ฐ์ ํน์ ๋ชจ๋ฐ์ผ์์ ์ ์กํ๊ฒ ๋์ด ์ค๋ฅ ์ ํ๋ฅผ ๋ง์์ฃผ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ๊ตฌ์ฒด์ ์ผ๋ก Hystrix๋ ์ด๋ป๊ฒ ๋์์ด ๋๋ ๊ฒ์ผ๊น์?
๋จผ์ HystrixCommand, HystrixObservableCommand ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ , Command๊ฐ ์คํ๋ฉ๋๋ค.
๋ง์ฝ, ๊ธฐ์กด์ ์ด๋ฏธ ์์ฒญํ ์ ์ด ์๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ ์บ์์ ์ ์ฅ๋์ด ์๋ค๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ์ ์กํฉ๋๋ค. ๊ทธ๋ ์ง ์๋ค๋ฉด, ์๋น์ค์ ๋์ ์ฌ๋ถ, ์ค๋ฅ ์ํ๋ฅผ ํ์ธํ๊ฒ ๋๊ณ , ๊ทธ๊ฒ์ด ์ ์์์ ํ์ธํ๋ค๋ฉด, ์ด์ Thread Pool, Queue, Semaphore๊ฐ ์๋์ง๋ฅผ ํ์ธํ๋๋ฐ, ์ด ๊ณผ์ ์ด ์ค์ํฉ๋๋ค. ๋ง์ฝ, Circuit Breaker ์ธ์คํด์ค์์๋ ์ด๋ฌํ ์ด์์ฒด์ ์์์ด ์๋ค๋ฉด, ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์ฌ๊ธฐ์ ์ด ๋ถ๋ถ์ด ์ค์ํ๋ฐ, Spring Application์ ๊ฐ๋ฐํ๊ณ , ์ฌ๋ฌ ์ฌ๋์ด ์ ์ํ๊ฒ ๋๋ฉด, ์ ํด์ง Thread ์์์ ๋ค ์ฐ๊ฒ ๋๋ ๋์ ๋ฌธ์ ๊ฐ ์์ฃผ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ํนํ Socket๊ณผ ๊ฐ์ ํต์ ์ ๊ฒฝ์ฐ๋ Linux Kernel์ ์ํฅ์ ๋ง์ด ๋ฐ๊ธฐ ๋๋ฌธ์ ์ค์ง์ ์ผ๋ก ๋ง์ด ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฏ๋ก Hystrix์์๋ ์ด๋ฌํ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ๋ฐ๋์ ๊ฑฐ์ณ์ผ ํฉ๋๋ค.
์์ ํ๋ณด๊ฐ ํ์ธ๋์๋ค๋ฉด, API ์๋น์ค์ ์์ฒญ์ ์ ๋ฌํ๊ฒ ๋๊ณ , ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ฉด Fallback ํจ์๋ฅผ ํตํด ์ค๋ฅ๋ฅผ ์ ๋ฌํ๊ณ , ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ, ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌํ๊ฒ ๋๋ ์ญํ ์ ํ๊ฒ ๋ฉ๋๋ค.
How to use
์ด์ ๊ฐ๋จํ ์ฌ์ฉ๋ฒ์ ์์๋ณผํ ๋ฐ, ์ด๋ฒ ํฌ์คํธ์์๋ Zuul Gateway, Eureka ๋ฑ์ ์๋น์ค ์์ด ๋จ์ํ API ์๋น์ค๋ง ๊ฐ์ง๊ณ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฒ์ ๋๋ค.
๋จผ์ Circuit Breaker ์ญํ ์ ํด์ค ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค. ๊ทธ๋ฌ๊ณ ๋ ํ, ์๋์ ๋ํ๋์๋ฅผ ์ถ๊ฐํด์ค์๋ค.
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.cloud:spring-cloud-starter-netflix-hystrix")
๊ฐ ๋ํ๋์๋ฅผ ๊ฐ๋จํ ์ค๋ช ๋๋ฆฌ์๋ฉด, WebFlux๋ Spring์์ REST API Client ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ณธ๋ RestTemplate์ด๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ง๋ง, ์ด ํฌ์คํธ์์๋ WebFlux ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์งํํ๊ฒ ์ต๋๋ค.
Hystrix๊ฐ ๋ฐ๋ก ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ Circuit Breaker์ ๋๋ค.
@EnableHystrix
@SpringBootApplication
class HystrixexampleApplication
fun main(args: Array<String>) {
runApplication<HystrixexampleApplication>(*args)
}
Application ํด๋์ค์ @EnableHystrix ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํด์ค๋๋ค.
/**
* Created by Neon K.I.D on 3/27/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@Service
class MemberResource {
private var client = WebClient.builder().baseUrl("http://localhost:8080").build()
@HystrixCommand(commandKey = "getNotes", fallbackMethod = "defaultMembers")
fun getMembers()
= client.get().uri("/v1/member/detail").retrieve().bodyToMono(String::class.java).block();
fun defaultMembers() = "ERROR"
}
๊ทธ๋ฐ ๋ค์ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ์์ ๊ฐ์ด ์ถ๊ฐํด์ค๋๋ค.
์ฝ๋์ ๋ํด์ ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ์๋ฉด, ์ด ์ปดํฌ๋ํธ๋ ์ค์ ๋ก ๋ธ๋ผ์ฐ์ ๋ ๋ชจ๋ฐ์ผ์์ ํธ์ถํ API ํจ์์ ๋๋ค. Hystrix๋ Java ์ฝ๋์์ Component, Service๋ฅผ ์ฐพ๊ณ , ๊ทธ ์์ ์๋ HystrixCommand ์ด๋ ธํ ์ด์ ์ ๋ฐ๋ผ ๋์ํ๋ ๊ตฌ์กฐ๋ก ๋์ด ์์ต๋๋ค. ๋ฐ๋ผ์ API ์๋ฒ์ ์๋ ๋ด์ฉ์ ๊ฐ์ ธ์ค๊ณ ์ ํ ๋๋ Component ๋ด์ง Service ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋๋ก ํฉ์๋ค.
๋์ถฉ ๋์น๋ฅผ ์ฑ์ จ๊ฒ ์ง๋ง, ๋ง์ฝ Member API์์ Member๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ, ์คํจํ์ ๊ฒฝ์ฐ, fallbackMethod๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก getMembers ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ์ง๋ง, ๋ง์ฝ ์ํท์ด Open๋์๊ฑฐ๋ ์์ฒญ์ ์คํจํ์ ๊ฒฝ์ฐ, defaultMembers ๋ฉ์๋๊ฐ ํธ์ถ๋๊ฒ ๋ฉ๋๋ค.
/**
* Created by Neon K.I.D on 3/28/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@RestController
class MemberController {
@Autowired
private lateinit var memberResource: MemberResource
@GetMapping(value = ["/members"])
fun getMembers() = memberResource.getMembers()
}
๋ง์ง๋ง์ผ๋ก REST API๋ฅผ ๊ตฌํํ๋ฉด ๋์ ๋๋ค.
Test
์ด์ ํ ์คํธ๋ฅผ ์งํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ํ ์คํธ๋ฅผ ์งํํ๊ธฐ ์ํด ๋จผ์ ์ง๋ ํฌ์คํธ์์ ๋ง๋ค์๋ Member API ์๋น์ค๋ฅผ ์คํ์ํค๊ณ , Circuit Breaker๋ฅผ ์คํํด ๋ด ์๋ค.
๋ ์๋น์ค ๋ชจ๋ ๊ฐ์ ๋ช ๋ น์ ํธ์ถํ๊ณ ์์์ ์ ์ ์์ต๋๋ค. ์ด์ API ์๋น์ค๋ฅผ ํ ๋ฒ ์ข ๋ฃํ ํ, ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋๋ก ํ์ฃ .
Member API ์๋น์ค๋ ์ฐ๊ฒฐ์ด ๋์ด์ง ์ํ์ด๊ณ , Circuit Breaker๊ฐ ์ด์ ๋ฐ๋ผ ์ ์๋ ํจ์๋ฅผ ํธ์ถํ์ฌ ERROR๋ฅผ ์ถ๋ ฅํด์ฃผ๊ณ ์์ต๋๋ค.
๋ง์น๋ฉฐ...
์ฌ๊ธฐ๊น์ง Hystrix์ ๊ฐ๋จํ ์ฌ์ฉ๋ฒ์ ๋ํด ์์๋ดค์ต๋๋ค. ์๋ง ์ค์ตํ์๋ ๋์ ๋ง์ ์๋ฌธ์ ์ด ๋์ จ์ ์๋ ์์ ๊ฒ์ ๋๋ค. ์ด์ ๊น์ง๋ Zuul Gateway๋ฅผ ์ด์ฉํด ๊ฐ๊ฐ ๋จ์ด์ง API๋ค์ ๋ฌถ์ด์ฃผ๊ณ ์ด๋ฅผ ๋ง๋ถ์ฌ ๋ก๋ ๋ฐธ๋ฐ์ฑ๋ ์ธ์คํด์ค๋ค์ Eureka๊ฐ ์ฐพ์์ฃผ์๋๋ฐ, ์ฌ๊ธฐ์ Circuit Breaker๊น์ง ๋ถ์ผ๋ฉด? ํ ..
์ฌ์ค ์ ์ Spring Cloud์ ํฌ์คํธ๋ Zuul Gateway๊น์ง๊ฐ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก ์งํ๋ ์์ ์ด์์ต๋๋ค. Circuit Breaker๋ ์ต์ ์ธ ํํ๋ก ์ ๊ณต๋ ์์ ์ด์์ต๋๋ค๋ง ๊ทธ ์ด์ ๋ Circuit Breaker๋ ๋ค์ํ ํํ๋ก ๊ตฌํ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฌ๋ฌ๋ถ๋ค์ด ์ํ๋ค๋ฉด Circuit Breaker๋ฅผ ์์ ๋ถ์ฌ๋๊ณ ๋จ๋ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ณ , Zuul Gateway, Riboon ๋ฑ ๋ค์ํ ์ปดํฌ๋ํธ์ ๋ฌถ์ด์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ์ธ์๋ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ํด ๋ค์ํ ํต๊ณ๋ฅผ ์ง๊ณํด์ ์๊ฐํ ํด์ฃผ๋ ๋์๋ณด๋, Hystrix์ ํ๋ ๋ฑ ๋ค์ํ ๊ฒ๋ค์ด ๋ง์ด ์์ด์ Hystrix๋ ์ฌ์ฉํ๊ธฐ๋ ๊ทธ๋งํผ ์ด๋ ต๊ณ , ๊น์ ๋ถ์ผ์ ๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ณธํธ์์๋ ์ด๋ฐ ์ฒ๋ฆฌ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๊ณ , ๋ ๋์๊ฐ์๋ ๋ด ์๋น์ค์ ์ด๋ค ์์ผ๋ก ์ ์ฉํด์ผ ํ ์ง๋ฅผ ๊ณ ๋ฏผํ์ ์ผ ํ ๊ฒ์ ๋๋ค.
์ด๋ฏธ์ง ์ถ์ฒ
(https://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html)
'Programming > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring boot] ๋ค์ํ ์ด๋ ธํ ์ด์ ์ ํ์ฉํ HTTP API ๊ตฌํ (0) | 2020.04.21 |
---|---|
[Spring boot] IntelliJ IDEA๋ฅผ ์ด์ฉํ Spring boot ํ๋ก์ ํธ ์์ (0) | 2020.04.21 |
[Spring Cloud] - 6. Eureka๋ฅผ ์ด์ฉํ ์๋น์ค ๊ฒ์ (0) | 2020.02.08 |
[Spring Cloud] - 5. Zuul Gateway๋ฅผ ์ด์ฉํ Filtering (0) | 2020.01.22 |
[Spring Cloud] - 4. Zuul Gateway๋ฅผ ์ด์ฉํ Routing (0) | 2020.01.17 |