LoginSignup
4
2

More than 3 years have passed since last update.

Netflix Hystrixが開発終了したのでResilience4jに移行

Last updated at Posted at 2019-08-30

環境

  • 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");
  }

参考
https://www.codeflow.site/ja/article/resilience4j

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2