Chapter 15 SeungminLee - JAVA-JIKIMI/SPRING-IN-ACTION-5 GitHub Wiki
์คํจ์ ์ง์ฐ ์ฒ๋ฆฌํ๊ธฐ
์ํท ๋ธ๋ ์ด์ปค ํจํด (circuit breaker pattern)
- ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋๊ฐ ์คํ์ ์คํจํ๋ ๊ฒฝ์ฐ ์์ ํ๊ฒ ์ฒ๋ฆฌ๋๋๋ก ํ๋ค.
- ๋ง์ดํฌ๋ก ์๋น์ค์์ ๋ ๋น์ ๋ฐํ๋ ํจํด
- ํ ๋ง์ดํฌ๋ก ์๋น์ค์ ์คํจ๊ฐ ๋ค๋ฅธ ๋ง์ดํฌ๋ก์๋น์ค์ ์ฐ์์ ์ธ ์คํจ๋ก ํ์ฐ์ด ๋๋ ๊ฑธ ๋ฐฉ์งํด์ผ ํ๊ธฐ ๋๋ฌธ์.
- ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์ฐจ๋จ๊ธฐ๋ฅผ ๋ด๋ ค ์ ๋ฅ๋ฅผ ๋ง๋ ์ค์ ํ๋ก (circuit)๊ณผ ์ ์ฌํ ํํ
- ์ด๋ค ์ด์ ๋ก ๋ฉ์๋์ ์คํ์ด ์คํจํ๋ฉด (์คํํ์๋ ์๊ฐ ๋ฑ ๋ฏธ๋ฆฌ ์ค์ ํด๋ ํ๊ณ๊ฐ์ ์ด๊ณผ) ์ํท ๋ธ๋ ์ด์ปค๊ฐ ๊ฐ๋ฐฉ์ด ๋๊ณ (์ฐจ๋จ๊ธฐ๋ฅผ ๋ด๋ฆฌ๊ณ ) ๋ ์ด์ ์คํจํ ๋ฉ์๋์ ํธ์ถ์ด ๋์ด์ ์ด๋ค์ง์ง ์๋๋ค.
- ์ด๋ ํ๋ฐฑ์ ์ ๊ณตํด ์์ฒด์ ์ผ๋ก ์คํจ๋ฅผ ์ฒ๋ฆฌํ๋ค.
- closed๊ฐ ์ํท์ํ์ ์์. (์ํท๋ธ๋ ์ด์ปค๋ก ๋ณดํธ๋๊ณ ์๋ ๋ฉ์๋)
- ์คํ์ ์ฑ๊ณตํ๋ฉด Success๋ผ ๋ซํ ์ํ๋ฅผ ์ ์ง
- ์คํจํ ์ ์ง๊ธ ์คํ๋๊ณ ์๋ ์คํจํ ๋ฉ์๋ ๋์ ํ๋ฐฑ ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค. ์ํ๋ open์ผ๋ก ๋ฐ๋๋ค
- ๋ง์ฝ ์๊ฐ์ด ์ง๋๋ ๋ฑ์ ์กฐ๊ฑด์ผ๋ก ์ธํด ์ํท์ด half-open ์ํ๊ฐ ๋๋ฉด ์คํจํ๋ ๋ฉ์๋๋ฅผ ๋ค์ ํธ์ถํด๋ณธ๋ค.
- ์ฑ๊ณตํ๋ฉด closed, ์คํจํ๋ฉด ๋ open ์ํ๊ฐ ๋๋ค.
์ํท ๋ธ๋ ์ด์ปค๋ฅผ ๋ ๊ฐ๋ ฅํ ํํ์ try-catch ๋ผ๊ณ ์๊ฐํ๋ฉด ์ข๋ค. ๋ซํ ์ํ๋(์ ์คํ์ด ๋จ) try์ ์ ์ฌํ๊ณ , ์คํจ ํ ํธ์ถ๋๋ ํ๋ฐฑ ๋ฉ์๋๋ catch ์ ์ ์ฌํ๋ค. try-catch๊ฐ ํ ๋ฒ์ ์คํจ๋ก ์คํ์ด ๋๋ค๋ฉด ์ํท ๋ธ๋ ์ด์ปค๋ ์ค์ ํ ํ๊ณ๊ฐ์ ๋์ด์ ์คํจํ์ ๊ฒฝ์ฐ ํ๋ฐฑ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
์ํท ๋ธ๋ ์ด์ปค๋ ๋ฉ์๋ ๋จ์๋ก ์ ์ฉ์ด ๋๋ค. ๋ฐ๋ผ์ ํ๋์ ๋ง์ดํฌ๋ก ์๋น์ค์ ๋ง์ ์ํค์ ๋ธ๋ ์ด์ปค๋ฅผ ๋ ์ ์๋ค. ๋๋ฌธ์ ์ฝ๋์ ์ด๋์ ์ํท ๋ธ๋ ์ด์ปค๋ฅผ ์ ์ธํ ์ง ๊ฒฐ์ ํ ๋๋ ์คํจ์ ๋์์ด ๋๋ ๋ฉ์๋(์คํจํ ์ํ์ด ์๋)๋ฅผ ์๋ณํ๋ ๊ฒ ์ค์ํ๋ค. ํ๋ณด๋ก ๋ฝ์ ์ ์๋ ๋ฉ์๋๋
- REST๋ฅผ ํธ์ถํ๋ ๋ฉ์๋ (์๊ฒฉ ์๋น์ค๋ก ์ธํด ์คํจ)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ์ํํ๋ ๋ฉ์๋ (๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ฌด๋ฐ์ ์ํ๊ฐ ๋ ์ ์๊ฑฐ๋ ์คํค๋ง ๋ณ๊ฒฝ์ผ๋ก ์ธํด ์คํจ)
- ๋๋ฆฌ๊ฒ ์คํ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ ๋ฉ์๋ (ํ์ ์คํจํ๋ ๋ฉ์๋๋ ์์ง์ง๋ง ๋๋ฌด ์ค๋ซ๋์ ์คํ๋๋ฉด ๋น์ ์์ ์ํ๋ฅผ ๊ณ ๋ ค)
1๊ณผ 2๋ ์ํท ๋ธ๋ ์ด์ปค๋ก ์คํจ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ง๋ง ๋ง์ง๋ง ์ ํ์ ๋ฉ์๋์ ์คํจ๋ณด๋ค๋ ์ง์ฐ(latency)๊ฐ ๋ฌธ์ ๋ค. ๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ์๋ ์ํท ๋ธ๋ ์ด์ปค์ ์ฅ์ ์ ์ด๋ฆด ์ ์๋ค. ์ง์ฐ์ ๋ง์ดํฌ๋ก์๋น์ค ๊ด์ ์์๋ ๋งค์ฐ ์ค์ํ๋ฐ, ์ง๋์น๊ฒ ๋๋ฆฐ ๋ฉ์๋๊ฐ ์์ ์๋น์ค์ ์ฐ์์ ์ธ ์ง์ฐ์ ์ ๋ฐํ๋ฉด ๋ ํฐ ๋ฌธ์ ๊ฐ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
์ฑ ์์ ์ฌ์ฉํ ์ํท ๋ธ๋ ์ด์ปค ํจํด์ NetFlix์ Hystrix๋ก, ์๋ฐ๋ก ๊ตฌํ์ด ๋์๊ณ ๋์ ๋ฉ์๋๊ฐ ์คํจํ ๋ ํด๋ฐฑ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋์์ ๋์ ๋ฉ์๋๊ฐ ์ผ๋ง๋ ์คํจ๋ฅผ ํ๋์ง ์ถ์ ํ๊ณ , ์คํจ์จ์ด ํ๊ณ๊ฐ์ ์ด๊ณผํ๋ฉด ํ๋ฐฑ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. ์ํท๋ธ๋ ์ด์ปค๋ฅผ ์ ์ธํ ๋๋ @HystrixCommand ๋ฅผ ์ ์ธํ๊ณ ํด๋ฐฑ ๋ฉ์๋๋ง ์ ๊ณตํด์ฃผ๋ฉด ๋๋ค.
- pom.xl์ dependency ์ถ๊ฐ
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- ์คํ๋ง ํด๋ผ์ฐ๋ ๋ฒ์ ์ง์ .
<properties>
...
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- application์ Hystrix ํ์ฑํ ํด์ฃผ๊ธฐ
@SpringBootApplication
@EnableHystrix
public class IngredientServiceApplication {
...
}
- @HystrixCommand ๋ฅผ ์ค์ ๋ฉ์๋์ ์ฌ์ฉํด๋ณด๊ธฐ
@HystrixCommand(fallbackMethod="getDefaultIngredients")
public Iterable<Ingredient> getAllIngredients() {
ParameterizedTypeReference<List<Ingredient>> stringList =
new ParameterizedTypeReference<List<Ingredient>>() {};
return rest.exchange(
"http://ingredient-service/ingredients", HttpMethod.GET,
HttpEntity.EMPTY, stringList).getBody();
}
- RestTemplate์ ์ฌ์ฉํด์ ์์์ฌ ์๋น์ค๋ก๋ถํฐ Ingredient ๊ฐ์ฒด๋ค์ด ์ ์ฅ๋ ์ปฌ๋ ์ ์ ๊ฐ์ ธ์ค๋ ๋ฉ์๋ getAllIngredients์ @HystrixCommand๋ฅผ ์ ์ฉํ๋ค.
- ์ค์ ๋ก ํต์ ์ ํ๋ exchange() ๊ฐ ํธ์ถ ์คํจ์ ์ ์ฌ์ ์ธ ์์ธ์ด๋ค.
- ์ด๋ ํ ์ด์ ๋ก ํธ์ถ์ด ์คํจํ๋ค๋ฉด RestClientException (unchecked, run-time exception)์ด ๋ฐ์ํ๋ค.
- RestTemplate์ด try-catch๋ฅผ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์ ์ง์ ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผ ํ๋๋ฐ ํ์ฌ๋ ํ์ง ์์ ์ํ๋ก, ์ด๋๋ก ์คํจํ๋ค๋ฉด ํธ์ถ ์คํ์ ์์ ํธ์ถ์๋ค์๊ฒ ๊ณ์ ์๋ฌ๊ฐ ์ ๋ฌ์ด ๋๋ค.
- ๊ณ์ ์ ๋ฌ๋๋ Unchecked์์ธ๋ ๊ณจ์นซ๊ฑฐ๋ฆฌ์ด๊ณ , ํนํ ์กฐ๋ฐํ๊ฒ ์ฐ๊ฒฐ์ด ๋์ด์๋ ๋ง์ดํฌ๋ก์๋น์ค์์ ๋ ์ฌํ๋ค.
- ๋ง์ดํฌ๋ก์๋น์ค์์ ์๊ธด ์๋ฌ๋ ๋ค๋ฅธ ๊ณณ์ ์ ํํ์ง ์๊ณ ํด๋น ๋ง์ดํฌ๋ก์๋น์ค์์ ๋จ๊ฒจ์ผ ํ๋ค(๋ง์ดํฌ๋ก์๋น์ค์ Vegas Rule)
- ์ด๋ getAllIngredients์ ์ํท๋ธ๋ ์ด์ปค๋ฅผ ์ ์ธํด์ฃผ๋ฉด ๋ฒ ๊ฐ์ค ๋ฃฐ์ ์งํฌ ์ ์๋ค.
- HystrixCommand ์ด๋ ธํ ์ด์ ์ ์ ์ธ ํ, fallback ๋ฉ์๋๋ฅผ getDefaultIngredients๋ก ์ง์
- ์คํจํ ๋ ์คํ์ด ๋ ํด๋ฐฑ ๋ฉ์๋ ๋ง๋ค๊ธฐ
private Iterable<Ingredient> getDefaultIngredients() {
List<Ingredient> ingredients = new ArrayList<>();
ingredients.add(new Ingredient(
"FLTO", "Flour Tortilla", Ingredient.Type.WRAP));
ingredients.add(new Ingredient(
"GRBF", "Ground Beef", Ingredient.Type.PROTEIN));
ingredients.add(new Ingredient(
"CHED", "Shredded Cheddar", Ingredient.Type.CHEESE));
return ingredients;
}
- unchecked ์์ธ๊ฐ ๋ฐ์ํด์ getAllIngredients๋ฅผ ๋ฒ์ด๋๋ฉด ์ํท๋ธ๋ ์ด์ปค๊ฐ ๊ทธ ์์ธ๋ฅผ ์๋ฐ์์ getDefaultIngredients๋ฅผ ํธ์ถํ๋ค.
- ํด๋ฐฑ๋ฉ์๋๋ ์๋์ ์๋๋๋ก ์คํจํ ๋ฉ์๋๊ฐ ์คํ์ด ๋ถ๊ฐ๋ฅํ ๋ ๋๋นํ๋ ์๋๋ก ๋ง๋๋ ๊ฒ์ด ์ ์ผ ์ข๋ค. (stand-alone ํํ, dummy ๋ฐ์ดํฐ๋ผ๋ ์ฑ์์ ์ค์ผํ๋ค)
- ํด๋ฐฑ ๋ฉ์๋๋ ์๋์ ๋ฉ์๋์ ์๊ทธ๋์ฒ๊ฐ ๊ฐ์์ผํ๋ค. ํ๋ผ๋ฉํฐ ์ข ๋ฅ, ๊ฐฏ์, ๋ฆฌํด๊ฐ์ด ๊ฐ์์ผ ํ๋ค.
- dummy ๊ฐ์ ์ฑ์์ฃผ๋ ์ด ๊ฒฝ์ฐ๋ ํด๋ฐฑ ๋ฉ์๋๊ฐ ์คํจํ ์ผ์ด ์์ง๋ง ๋ค๋ฅด๊ฒ ๊ตฌํ์ ํ๋ค๋ฉด ์ด ๋ฉ์๋ ๋ํ ์ ์ฌ์ ์ธ ์คํจ๊ฐ ๋ ์ ์๋ค.
- ์ด๋ ์ด ํด๋ฐฑ ๋ฉ์๋์ HytrixCommand๋ฅผ ๋ฌ๊ณ ํด๋ฐฑ ๋ฉ์๋๋ฅผ ๋ ์ง์ ์ ํ ์ ์๋ค. ์ํท ๋ธ๋ ์ด์ปค๋ ์ฐ์์ ์ผ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
- ๋จ, ํด๋ฐฑ ์คํ์ ์ ์ผ ๋ฐ์๋ ์คํ์ ์คํจํ์ง ์์ ์ํท ๋ธ๋ ์ด์ปค๊ฐ ํ์์๋ ํ์คํ ๋ฉ์๋๊ฐ ์ด์ด์ผ ํ๋ค.
์ํท ๋ธ๋ ์ด์ปค๋ ๋ฉ์๋์ ์คํ์ด ๋๋๊ณ ๋ณต๊ทํ๋ ์๊ฐ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆด ๊ฒฝ์ฐ ํ์์์์ ์ฌ์ฉํด ์ง์ฐ์๊ฐ์ ์ค์ผ ์ ์๋ค. HystrixCommand๋ฅผ ์ง์ ํ๋ฉด ๋ํดํธ๋ก ๋ฉ์๋๋ 1์ดํ์ ํ์์์์ด ๋๊ณ ํด๋ฐฑ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค. ์ด์ ๋ฅผ ๋ถ๋ฌธํ๊ณ ํ์์์์ด ๋๋ฉด ๋ฌด์กฐ๊ฑด ํ๋ฐฑ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
1์ด์ ํ์์์์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ ๋ง๋ ํฉ๋ฆฌ์ ์ธ ๊ฐ์ด์ง๋ง Hystrix๋ commandProperties๋ฅผ ํตํด ์์ฑ์ ์ง์ ํ์ฌ ํ์์์์ ๋ณ๊ฒฝํ ์ ์๋ค. commandProperties๋ ์ค์ ๋ ์์ฑ์ ์ด๋ฆ๊ณผ ๊ฐ์ ์ง์ ํ๋ ํ๋ ์ด์์ @HystrixProperty ์ด๋ ธํ ์ด์ ์ ์ ์ฅํ ๋ฐฐ์ด์ด๋ค.
(์ด๋ ธํ ์ด์ ์ ์ด์ฉํด์ ๋ค๋ฅธ ์ด๋ ธํ ์ด์ ์ ์์ฑ์ ์ค์ ํ๋ค๋ ์ฑ๊ฒฉ์ด ๋ค์ ํน์ดํ๋ค)
@HystrixCommand(
fallbackMethod="getDefaultIngredients",
commandProperties={
@HystrixProperty(
name="execution.isolation.thread.timeoutInMilliseconds",
value="500")
})
public Iterable<Ingredient> getAllIngredients() {
...
}
@HystrixCommand(
fallbackMethod="getDefaultIngredients",
commandProperties={
@HystrixProperty(
name="execution.timeout.enabled",
value="false")
})
public Iterable<Ingredient> getAllIngredients() {
...
}
- execution.isolation.tread.timeoutMilliseconds : ํ์์์ ์์ฑ ์ค์ , ๋ฐ๋ฆฌ์ธ์ปจ๋๋ก ๋์ด์์ด ํ์์์์ 0.5 ์ด๋ก ์ค์ด๊ณ ์ ํ๋ค๋ฉด 500์ผ๋ก ์ค์ ํ๋ฉด ๋๋ค.
- execution.timeout.enabled: ํ์์์ ์ค์ ์ด ํ์์๋ค๋ฉด ์ฌ๊ธฐ๋ฅผ false๋ก ํด์ฃผ๋ฉด ๋๋ค.
- ์ด์ฒ๋ผ ํ์์์์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ๋ฉ์๋๊ฐ ์ง์ฐ๋์ด 10๋ถ 30๋ถ์ด ์ง๋๋ ๋จธ๋ฌผ๋ฌ์๊ธฐ ๋๋ฌธ์ ์ฐ์ ์ง์ฐ ํจ๊ณผ๊ฐ ๋ฐ์ํ๋ฏ๋ก ์ฃผ์ํด์ผํ๋ค.
์ํท๋ธ๋ ์ด์ปค๋ก ๊ฐ์ธ์ง ๋ฉ์๋๋ ๊ธฐ๋ณธ์ผ๋ก 10์ด ๋์์ 20๋ฒ ์ด์ ํธ์ถ๋๊ณ ์ด ์ค 50%์ด์์ด ์คํจํ๋ฉด ์ด๋ฆผ ์ํ๊ฐ ๋๋ค. ์ดํ์ ๋ชจ๋ ํธ์ถ์ ํด๋ฐฑ ๋ฉ์๋์ ์ํด ์ฒ๋ฆฌ๋๋ค๊ฐ 5์ดํ์ half-open ์ํ๊ฐ ๋์ด ์๋ ๋ฉ์๋ ํธ์ถ์ ์๋ํ๋ค.
@HystrixCommand(
fallbackMethod="getDefaultIngredients",
commandProperties={
@HystrixProperty(
name="circuitBreaker.requestVolumeThreshold",
value="30"),
@HystrixProperty(
name="circuitBreaker.errorThresholdPercentage",
value="25"),
@HystrixProperty(
name="metrics.rollingStats.timeInMilliseconds",
value="20000")
@HystrixProperty(
name="circuitBreaker.sleepWindowInMilliseconds",
value="60000")
})
public List<Ingredient> getAllIngredients() {
// ...
}
- circuitBreaker.requestVolumeThreshold : ์ง์ ๋ ์๊ฐ ๋ด์ ๋ฉ์๋๊ฐ ํธ์ถ๋์ด์ผํ๋ ํ์
- circuitBreaker.errorThresholdPercentage : ์ง์ ๋ ์๊ฐ ๋ด์ ์คํจํ ๋ฉ์๋ ํธ์ถ ๋น์จ (%)
- metrics.rollingStats.timeInMilliseconds : ์์ฒญ ํ์์ ์๋ฌ ๋น์จ์ด ๊ณ ๋ ค๋๋ ์๊ฐ
- circuitBreaker.sleepWinfowInMilliseconds : half-open ์ํ๋ก ์ง์ ํ์ฌ ์คํจํ ๋ฉ์๋๊ฐ ๋ค์ ์๋๋๊ธฐ ์ ์ ์ด๋ฆผ ์ํ์ ์ํท์ด ์ ์ง๋๋ ์๊ฐ
metrics.rollingState.timeMilliseconds์ ์ง์ ๋ ์๊ฐ ์ด๋ด์ circuitBreaker.requestVolumeThreshold์ circuitBreaker.errorThresholdPercentage ๊ฐ ์ด๊ฐ๋๋ค๋ฉด circuitBreaker.sleepWinfowInMilliseconds ์ ์ง์ ๋ ์๊ฐ๋์ ์ด๋ฆผ ์ํ์์ ๋จธ๋ฌด๋ฅธ๋ค.
์์ ์ฝ๋์ ๊ฐ์ด ์ค์ ์ ํ๋ค๋ฉด 20์ด ์ด๋ด์ ๋ฉ์๋๊ฐ 30๋ฒ ์ด์ ์ดํ์ด ๋์ด ์ด์ค 25%๊ฐ ์คํจ์ผ๊ฒฝ์ฐ ์ํท์ ์ด๋ฆผ ์ํ๊ฐ ๋๊ณ 1๋ถ๊ฐ ํด๋ฐฑ ๋ฉ์๋๊ฐ ์์ฒญ์ ๋์ ๋ฐ์์ ์ฒ๋ฆฌํ๋ค.
๋ฉ์๋ ์คํจ์ ์ง์ฐ์ ์ฒ๋ฆฌํ๋ ๊ฒ ์ธ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์๋ ๊ฐ ์ํท ๋ธ๋ ์ด์ปค์ ๋ฉํธ๋ฆญ๋ ์คํธ๋ฆผ์ผ๋ก ๋ฐํ์ ํ๋ค. ์์ผ๋ก๋ Hystrix๊ฐ ๋ฐํํ ์คํธ๋ฆผ์ผ๋ก ์ดํ๋ฆฌํ ์ด์ ์ ์ํ๋ฅผ ๋ชจ๋ํฐ๋งํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ๋ค.
์ํท ๋ธ๋ ์ด์ปค๋ก ๋ณดํธ๋๋ ๋ฉ์๋๊ฐ ๋งค๋ฒ ํธ์ถ๋ ๋๋ง๋ค ํด๋น ํธ์ถ์ ๊ดํ ์ฌ๋ฌ ๋ฐ์ดํฐ๊ฐ ์์ง๋์ด Hystrix ์คํธ๋ฆผ์ผ๋ก ๋ฐํ๋๋ค. ์์์ ๋งํ ๊ฒ์ฒ๋ผ ์ด ์คํธ๋ฆผ์ ์คํ์ค์ธ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋งํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ค. Hystrix ์คํธ๋ฆผ ์์๋ ์๋์ ์ฌํญ๋ค์ด ํฌํจ๋๋ค.
- ๋ฉ์๋๊ฐ ๋ช ๋ฒ ํธ์ถ๋๋์ง
- ์ฑ๊ณต์ ์ผ๋ก ๋ช ๋ฒ ํธ์ถ๋๋์ง
- ํ๋ฐฑ ๋ฉ์๋๊ฐ ๋ช ๋ฒ ํธ์ถ๋๋์ง
- ๋ฉ์๋๊ฐ ๋ช ๋ฒ ํ์์์๋๋์ง
์ด์ ๊ฐ์ Hystrix ์คํธ๋ฆผ์ ํ์ฑํํ๊ธฐ ์ํ ๋ฐฉ๋ฒ
- pom.xml์ dependency ์ถ๊ฐ
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- Hystrix ์ค๋ํฌ์ธํธ ๊ฒฝ๋ก ๋ ธ์ถ์ํค๊ธฐ
management:
endpoints:
web:
exposure:
include: hystrix.stream
2๋ฒ์ ๋ง์ดํฌ๋ก์๋น์ค์ ์ฌ์ฉ์ด ๋๋ ๊ฐ ์ดํ๋ฆฌ์ผ์ด์ ์ application.yml ํ์ผ์ ์ถ๊ฐ์์ผ์ฃผ๋ฉด ๊ตฌ์ฑ ์๋ฒ์ ๋ชจ๋ ํด๋ผ์ด์ธํธ ์๋น์ค๊ฐ ์ด ์์ฑ์ ์ฌ์ฉํ ์ ์๋ค.
์ด์ Hystrix ์คํธ๋ฆผ์ด ๋ ธ์ถ๋์ด ์ด๋ค REST ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํด๋ ์คํธ๋ฆผ์ ์ฌ์ฉํ ์ ์์ง๋ง ๊ทธ๋ฅ Hystrix ์คํธ๋ฆผ์ ๊ฐ ํญ๋ชฉ์ ๊ฐ์ JSON ๋ฐ์ดํฐ๋ก ๊ตฌ์ฑ์ด ๋์ด์๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ ์ธก์ ๋ง์ ์์ ์ ์ํ์ง ์๋๋ค๋ฉด Hystrix ๋์๋ณด๋์ ์ฌ์ฉ์ ๊ณ ๋ คํด๋ณด์.
(์๋ก์ด ์คํ๋ง๋ถํธ ํ๋ก์ ํธ๋ก ์งํํด์ผ ํ๋ค)
- pom.xml dependency ์ถ๊ฐ
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
- application์์ ํ์ฑํ๋ฅผ ์ํด @EnableHysritxDashboard ์ถ๊ฐ
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
- ํฌํธ ์ถฉ๋ ์๋ฐฉ์ ์ํ ์๋ฒ ํฌํธ ์ง์ (๊ฐ๋ฐ์ ๋ก์ปฌ์์ ์ฌ๋ฌ๊ฐ์ง ์๋ฒ๋ฅผ ๋๋ฆฌ๊ณ ์์ ๊ฒฝ์ฐ)
server:
port: 7979
- Hystrix ๋ฅผ ๊ตฌํํด ์คํธ๋ฆผ์ ๋ฐ์์ค๋ ์๋น์ค ์ดํ๋ฆฌ์ผ์ด์ ์ ์คํธ๋ฆผ์ ๋ณด๊ธฐ ์ํด์๋ ๊ณ ์ด๋์น ๋ฐ์ ์๋ ์ฐฝ์ ํด๋น ์ดํ๋ฆฌ์ผ์ด์ ํฌํธ์ strem url์ ์จ์ฃผ๋ฉด ๋๋ค. localhost:8080/hystrix.stream (์๊นhystrix์ ์ค๋ํฌ์ธํธ๋ฅผ hystrix.stream์ผ๋ก ์ค์ )
- Delay: ํด๋ง ๊ฐ๊ฒฉ์ ๋ํ๋ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ์ 2์ด. ๊ฒฐ๊ตญ hystrix.stream ์ค๋ํฌ์ธํธ๋ก๋ถํฐ 2์ด์ ํ๋ฒ์ฉ Hystrix ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์จ๋ค
- Title: ๋ชจ๋ํฐ ํ์ด์ง ์ ๋ชฉ
- getAllIngredients์ ๋ํ ๋ชจ๋ํฐ๋งํ๋ฉด (์ ์ผํ ์ํท ๋ธ๋ ์ด์ปค)
- ๋ง์ฝ Loding์ด๋ผ๋ ๋จ์ด๋ง ๋ณด์ธ๋ค๋ฉด ์ํท ๋ธ๋ ์ด์ปค๋ก ๋ณดํธ๋ ๋ฉ์๋์ ํธ์ถ์ด ์์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋์๋ณด๋์ ๊ฐ์ ํํํ๊ณ ์ถ์ผ๋ฉด ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ํ๋ค.
(๋ ์์ธํ ๋์๋ณด๋)
- ์ผ์ชฝ ์ ๋ชจ์๋ฆฌ์ ๊ทธ๋ํ: ์ง์ ๋ ๋ฉ์๋์ ์ง๋ 2๋ถ ๋์์ ํธ๋ํฝ์ ๋ํ๋ด๋ฉฐ, ๋ฉ์๋๊ฐ ์ผ๋ง๋ ๋ฐ์๊ฒ ์คํ๋์๋์ง ๋ณผ ์ ์๋ค.
- ์๊น์ด ์ ํ์ง ์: ์์ ํฌ๊ธฐ๋ ํ์ฌ์ ํธ๋ํฝ ์๋์ด๋ฉฐ ์์ ์์์ ํด๋น ์ํท ๋ธ๋ ์ด์ปค์ ์ํ๋ฅผ ๋ํ๋ธ๋ค. (์ด๋ก: ์ข์, ๋ ธ๋: ๊ฐ๋ ์คํจ, ๋นจ๊ฐ: ์คํจ)
- ์ค๋ฅธ์ชฝ ์ ์ฒซ์งธ ์ด: (์๋์ชฝ์ผ๋ก ์ฝ๊ธฐ) ์ฒซ๋ฒ์งธ: ํ์ฌ ์ฑ๊ณตํ ํธ์ถ ํ์, ๋๋ฒ์งธ: short circuited ์์ฒญ ํ์, ๋ง์ง๋ง: ์๋ชป๋ ์์ฒญ์ ํ์
- ๋๋ฒ์งธ ์ด: ํ์ ์์๋ ์์ฒญ ํ์/์ค๋ ๋ ํ์ด ๊ฑฐ๋ถํ ํ์/์คํจํ ์์ฒญ ํ์
- ์ธ๋ฒ์งธ ์ด: ์ง๋ 10์ด๊ฐ์ ์๋ฌ ๋น์ต
- Host์ Cluster์ ์ด๋น ์์ฒญ ์๋ฅผ ๋ํ๋ด๋ ์ซ์ ๋๊ฐ, ๊ทธ ์๋๋ก๋ ํด๋น ์ํท ๋ธ๋ ์ด์ปค์ ์ํ.
- ์ ์ผ ์๋: ์ง์ฐ์๊ฐ์ ์ค๊ฐ๊ฐ๊ณผ ํ๊ท ์น, ๋ฐฑ๋ถ์ ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์๋ค.
๋๋ฌด ์ํ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๋ฉ์๋ โ ๋ค๋ฅธ ์๋น์ค์ Http ์์ฒญ์ ํ๊ณ ์๋๋ฐ ํด๋น ์๋น์ค์ ์๋ต์ด ๋๋ฆผโ ์ด๋ฐ ๊ฒฝ์ฐ Hystrix๋ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ๊ด๋ จ ์ค๋ ๋๋ฅผ ๋ธ๋กํนํ๋ค.
์ด๋ฐ ๋ฉ์๋๊ฐ ํธ์ถ์์ ๊ฐ์ ์ค๋ ๋์ ์ปจํ ์คํธ์์ ์คํ ์ค์ด๋ผ๋ฉด ํธ์ถ์๋ ์ค๋ ์คํ๋๋ ๋ฉ์๋๋ก๋ถํฐ ๋ฒ์ด๋ ๊ธฐํ๊ฐ ์๋ค. ๊ฒ๋ค๊ฐ ๋ธ๋กํน๋ ์ค๋ ๋๊ฐ ์ ํ๋ ์์ ์ค๋ ๋ ์ค ํ๋์ธ๋ฐ ๋ฌธ์ ๊ฐ ๊ณ์ ์๊ธด๋ค๋ฉด ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ์ค๋ ๋๊ฐ ํฌํ ์ํ๊ฐ ๋์ด ์๋ต์ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ค.
์ด๋ฐ ์ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด Hystrix๋ ๊ฐ ์์กด์ฑ ๋ชจ๋์ ์ค๋ ๋ ํ์ ํ ๋นํ๋ค. (ํ๋ ์ด์์ Hystrix ๋ช ๋ น ๋ฉ์๋๋ฅผ ๊ฐ๋ ๊ฐ ์คํ๋ง ๋น์ ์ํด)
โ Hystrix ๋ช ๋ น ๋ฉ์๋ ์ค ํ๋๊ฐ ํธ์ถ๋ ๋ ์ด ๋ฉ์๋๋ Hystrix๊ฐ ๊ด๋ฆฌํ๋ ์ค๋ ๋ ํ์ ์ค๋ ๋(ํธ์ถ ์ค๋ ๋์๋ ๋ณ๋) ์์ ์คํ์ด ๋๋ค.
โ ๋ฐ๋ผ์ ์ด ๋ฉ์๋๊ฐ ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฐ๋ค๋ฉด ํธ์ถ ์ค๋ ๋๋ ํด๋น ํธ์ถ์ ํฌ๊ธฐํ๊ณ ๋ฒ์ด๋๋ฉฐ, ์ ์ฌ์ ์ธ ์ค๋ ๋ ํฌํ๋ฅผ Hystrix๊ฐ ๊ด๋ฆฌํ๋ ์ค๋ ๋ ํ์ ๋ฒ๋ฆด ์ ์๋ค.
(์ฐ๋ ๋ ํ์ ์ค์ ์ ๋ ๋์๋ณด๋, ์ํท ๋ธ๋ ์ด์ปค ๋ชจ๋ํฐ์ ํก์ฌํ ํํ)
- ์ํ๋ฅผ ๋ํ๋ด๋ ์์ด ์๋ ๊ฒ์ ๋์ผํ๋ ์ง๋ ๋ช ๋ถ ๋์์ ์ค๋ ๋ ํ ํ๋์ ๋ํ๋ด๋ ์ ๊ทธ๋ํ๋ ์๋ค.
- ์ค๋ ๋ ํ์ ์ด๋ฆ: ingredientServiceImpl
- ์ผ์ชฝ ์๋ ๋ชจ์๋ฆฌ : ํ์ฑ ์ค๋ ๋์ ํ์ฌ ๊ฐ์/ํ์ฌ ํ์ ์๋ ์ค๋ ๋ ๊ฐ์(๊ธฐ๋ณธ์ ์ผ๋ก ํ๊ฐ ๋นํ์ฑํ ๋์ด์์ด์ ๊ฐ์ ํญ์ 0)/์ค๋ ๋ ํ์ ์๋ ์ค๋ ๋์ ๊ฐ์
- ์ค๋ฅธ์ชฝ ์๋ ๋ชจ์๋ฆฌ: ์ํ๋ง ์๊ฐ๋์ ์ต๋ํ์ฑ ์ค๋ ๋ ์นด์ดํธ/Hystrix ์คํ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ค๋ ๋ ํ์ ์ค๋ ๋๊ฐ ํธ์ถ๋ ํ์/์ค๋ ๋ ํ ์์ ํฌ๊ธฐ(๊ธฐ๋ณธ ๋นํ์ฑ)
์๋ Hystrix ๋์๋ณด๋๋ ํ ๋ฒ์ ํ๋์ Hystrix ์คํธ๋ฆผ์ ๋ชจ๋ํฐ๋ง ํ ์ ์์ง๋ง Netflix์ Turbine ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐํํ๋ ์คํธ๋ฆผ์ ํ๋๋ก ์ข ํฉํด์ค๋ค.
(์๋ก์ด ์คํธ๋ง๋ถํธ ํ๋ก์ ํธ์ ์งํํด์ผ ํ๋ค.
- pom.xml์ dependency ์ถ๊ฐ
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
- application์ ํ์ฑํ๋ฅผ ์ํด @EnableTurbine ์ถ๊ฐ
@SpringBootApplication
@EnableTurbine
public class TurbineServerApplication {
public static void main(String[] args) {
SpringApplication.run(TurbineServerApplication.class, args);
}
}
- ์๋น์ค ํฌํธ ์ถฉ๋์ ๋ง๊ธฐ ์ํด ์๋ฒ ํฌํธ ์ค์
server:
port: 8989
์ด์ ๋ง์ดํฌ๋ก์๋น์ค๋ก๋ถํฐ Hystrix ์คํธ๋ฆผ์ด ์์ฑ๋๋ฉด ์ํท ๋ธ๋ ์ด์ปค ๋ฉํธ๋ฆญ๋ค์ด Turbine์ ์ํด ํ๋์ Hystrix ์คํธ๋ฆผ์ผ๋ก ์ข ํฉ์ด ๋๋ค. Trubine์ ์ ๋ ์นด์ ํด๋ผ์ด์ธํธ๋ก ์๋ํ๋ฏ๋ก Hystrix ์คํธ๋ฆผ์ ์ข ํฉํ ์๋น์ค๋ค์ ์ ๋ ์นด์ ์ฐพ๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ชจ๋ ์๋น์ค์ ์คํธ๋ฆผ์ ์ข ํฉํ์ง๋ ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ค์ ์ ํด์ฃผ์ด์ผ ํ๋ค.
- turbine.app-config ์์ฑ์ ์ฌ์ฉํด Hystrix ์คํธ๋ฆผ ์ข ํฉ ์ค์ ํ๊ธฐ
turbine:
app-config: ingredient-service,taco-service,order-service,user-service
cluster-name-expression: "'default'"
- ์ ๋ ์นด์์ ์ฐพ์ ์๋น์ค ์ด๋ฆ๋ค์ ์ค์ ํ๋ค.
- ์ด๋ฆ์ด default์ธ ํด๋ฌ์คํฐ์ ์๋ ๋ชจ๋ ์ข ํฉ๋ ์คํธ๋ฆผ์ Turbine์ด ์์งํ๋ค(cluster0name-expression)
- ๋ง์ฝ ์ด๋ฆ์ ์ค์ ํ์ง ์์ผ๋ฉด ์ง์ ๋ ์ดํ๋ฆฌ์ผ์ด์ ๋ค๋ก๋ถํฐ ์ข ํฉ๋ ์ด๋ค ์คํธ๋ฆผ ๋ฐ์ดํฐ๋ Turbine ์คํธ๋ฆผ์ ํฌํจ์ด ์๋๋ค.
- localhost:8989/turbine.stream ๋ฅผ ๋์๋ณด๋์ ์ ๋ ฅ
- ์ํท ๋ธ๋ ์ด์ปค ํจํด์ ์ ์ฐํ ์คํจ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋ค.
- Hystrix๋ ๋ฉ์๋๊ฐ ์คํ์ ์คํจํ๊ฑฐ๋ ๋๋ฌด ๋๋ฆด ๋ ํด๋ฐฑ ์ฒ๋ฆฌ๋ฅผ ํ์ฑํํ๋ ์ํท ๋ธ๋ ์ด์ปค ํจํด์ ๊ตฌํํ๋ค
- Hystrix๊ฐ ์ ๊ณตํ๋ ๊ฐ ์ํท ๋ธ๋ ์ด์ปค๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ๋ชจ๋ํฐ๋งํ ๋ชฉ์ ์ผ๋ก Hystrix ์คํธ๋ฆผ ๋งคํธ๋ฆญ์ค๋ฅผ ๋ฐํํ๋ค.
- Hystrix ์คํธ๋ฆผ์ Hystrix ๋์๋ณด๋๊ฐ ์ฌ์ฉํ ์ ์๋ค. Hystrix ๋์๋ณด๋๋ ์ํท ๋ธ๋ ์ด์ปค ๋งคํธ๋ฆญ์ค๋ฅผ ๋ณด์ฌ์ฃผ๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ด๋ค.
- Turbine์ ์ฌ์ฉํ๋ฉด ์ดํ๋ฆฌ์ผ์ด์ ๋ค์์ ๋ฐํ์ด ๋๋ ์คํธ๋ฆผ์ ํ๋๋ก ๋ณํฉํ ์ ์๋ค.
- Hystrix ํจํด์ ๋ํ ๋ ์์ธํ ์ค๋ช
- Hystrix ๋ฅผ ์ฌ์ฉํ๊ฒ ๋ ์ฐ์ํ ํ์ ๋ค์ ์ค์ ๊ฐ๋ฐ ์ฌ๋ก
Hystrix! API Gateway๋ฅผ ๋์์ค! - ์ฐ์ํํ์ ๋ค ๊ธฐ์ ๋ธ๋ก๊ทธ
- ๊ฐ๋จํ๊ฒ ๋ง๋ค ์ ์๋ Hystrix ๊ตฌํ ์์
Hystrix Circuit Breaker Pattern - Spring Cloud - HowToDoInJava