環境
- Spring Boot 2.1.0.RELEASE
- Java 8
Netflix Hystrix
https://github.com/Netflix/Hystrix
↑いわく、最後のコミットをしたよ、とのこと。
脆弱性とかバグとかが見つかる前に移行します。
resilience4j
ソース
POM
pom.xml
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>0.17.0</version>
</dependency>
リファレンス
移行前のソース
MyContoller.java
// Contollerの修正はなし
@Slf4j
@Controller
@RequestMapping("/example")
@RequiredArgsConstructor
public class MyController {
@NonNull
MyService service;
@PostMapping("/post")
public String doPostForm() throws Exception {
if(service.registration()) {
return "成功時の遷移先";
}
return "失敗時の遷移先";
}
}
MyService.java
public class MyService {
@Transactional(readOnly = false)
// CircuitBreakerの設定
@HystrixCommand(fallbackMethod = "fallback", commandProperties = {
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000"),
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")})
public boolean registration(MyParameter param,
String) throws Exception {
// connect to external api...
return true;
}
/**
* fallback時に実行
*/
public boolean fallback(Throwable t) {
log.warn("circuit breaker open", t);
return false;
}
}
移行後のソース
application.yml
resilience4j:
circuitbreaker:
configs:
default:
registerHealthIndicator: true
ringBufferSizeInClosedState: 10
ringBufferSizeInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 2s
failureRateThreshold: 50
eventConsumerBufferSize: 10
instances:
myCircuitBreaker:
baseConfig: default
MyService.java
// ~~ importは省略 ~~
import io.vavr.control.Try;
public class MyService {
CircuitBreaker circuitBreaker;
@NonNull
CircuitBreakerRegistry registry;
@PostConstruct
public void init() {
circuitBreaker = registry.circuitBreaker("myCircuitBreaker");
}
@Transactional(readOnly = false)
public boolean registration(MyParameter param) throws Exception {
return Try.ofSupplier(CircuitBreaker.decorateSupplier(circuitBreaker,
MyStreamHelper.throwingSupplier(() -> {
// connect to external api...
return true
})))
// Circuit Breaker Open時に実行する処理
.recover(throwable -> {
return fallback(throwable);
}).get();
}
/**
* fallback時に実行
*/
private boolean fallback(Throwable t) {
log.warn("circuit breaker open", t);
return false;
}
}
補足
MyStreamHelper
については下記をご参照ください。
try-catchを隠しているだけです。
https://shironeko.hateblo.jp/entry/2016/07/16/140236
2020/07/10追記
ymlではなくJavaに設定値を書く場合
// Bean登録する場合の書き方。
// 利用する側はcircuitBreakerをDIすることでmyCircuitBreakerが利用できる。
@Bean
public CircuitBreaker circuitBreaker() {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
// ymlに書いていた値をここに書いていく
.failureRateThreshold(20)
.build();
return CircuitBreakerRegistry.of(config).circuitBreaker("myCircuitBreaker");
}