resilience4j如何在Spring webflux应用程序中使用断路器时处理错误

时间:2018-03-14 11:44:08

标签: project-reactor spring-webflux circuit-breaker resilience4j

现在当电路打开时,连接只是保持打开而没有响应。

如果我停止服务器,浏览器会显示:

Whitelabel Error Page

This application has no configured error view, so you are seeing this as a fallback.
Wed Mar 14 12:55:08 CET 2018
There was an unexpected error (type=Internal Server Error, status=500).
CircuitBreaker 'gamesCircuitBreaker' is open

我想知道如何:

1)解决挂断连接的问题。

2)返回一些东西作为后备。例如,一个空的Flux。

@Component
class ApiHandlers(private val gamesRepository: GamesRepository) {

    val circuitBreakerConfig : CircuitBreakerConfig = CircuitBreakerConfig.custom()
            .failureRateThreshold(50f)
            .waitDurationInOpenState(Duration.ofMillis(10000))
            .ringBufferSizeInHalfOpenState(5)
            .ringBufferSizeInClosedState(5)
            .build()
    var circuitBreaker: CircuitBreaker = CircuitBreaker.of("gamesCircuitBreaker", circuitBreakerConfig)

    fun getGames(serverRequest: ServerRequest): Mono<ServerResponse> {
        println("*********${circuitBreaker.state}")
        return ok().body(gamesRepository.findAll().transform(CircuitBreakerOperator.of(circuitBreaker)), Game::class.java)
    }
}

@Configuration
class ApiRoutes(private val apiHandlers: ApiHandlers) {

    @Bean
    fun apiRouter() = router {
        "/api/v1".nest {
            GET("/games", apiHandlers::getGames)
        }
    }
}

日志:

*********OPEN
2018-03-14 12:55:08.809 DEBUG 1789 --- [ctor-http-nio-4] i.g.r.c.i.CircuitBreakerStateMachine     : No Consumers: Event NOT_PERMITTED not published
2018-03-14 12:55:08.813 ERROR 1789 --- [ctor-http-nio-4] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://localhost:8081/api/v1/games]

io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException: CircuitBreaker 'gamesCircuitBreaker' is open
    at io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerSubscriber.hookOnSubscribe(CircuitBreakerSubscriber.java:57) ~[resilience4j-reactor-0.12.0.jar:0.12.0]
    at reactor.core.publisher.BaseSubscriber.onSubscribe(BaseSubscriber.java:146) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators.error(Operators.java:174) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxError.subscribe(FluxError.java:43) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at io.github.resilience4j.reactor.circuitbreaker.operator.FluxCircuitBreaker.subscribe(FluxCircuitBreaker.java:34) ~[resilience4j-reactor-0.12.0.jar:0.12.0]
    at reactor.core.publisher.MonoCollectList.subscribe(MonoCollectList.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxSourceMonoFuseable.subscribe(FluxSourceMonoFuseable.java:38) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at org.springframework.http.server.reactive.ChannelSendOperator.subscribe(ChannelSendOperator.java:74) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1069) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1626) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapInner.onSubscribe(MonoFlatMap.java:230) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:271) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:803) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1626) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1440) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1314) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:128) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:61) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:167) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:70) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:380) ~[reactor-netty-0.7.5.RELEASE.jar:0.7.5.RELEASE]
    at reactor.ipc.netty.http.server.HttpServerOperations.onHandlerStart(HttpServerOperations.java:397) ~[reactor-netty-0.7.5.RELEASE.jar:0.7.5.RELEASE]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463) ~[netty-transport-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) ~[netty-common-4.1.22.Final.jar:4.1.22.Final]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_161]

2018-03-14 12:55:08.816  WARN 1789 --- [ctor-http-nio-4] i.n.u.concurrent.AbstractEventExecutor   : A task raised an exception. Task: reactor.ipc.netty.channel.ContextHandler$$Lambda$295/435712160@2f597a11

reactor.core.Exceptions$BubblingException: java.lang.RuntimeException: fail
    at reactor.core.Exceptions.bubble(Exceptions.java:154) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators.onErrorDropped(Operators.java:256) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.BaseSubscriber.onError(BaseSubscriber.java:172) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators.error(Operators.java:175) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxError.subscribe(FluxError.java:43) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at io.github.resilience4j.reactor.circuitbreaker.operator.FluxCircuitBreaker.subscribe(FluxCircuitBreaker.java:34) ~[resilience4j-reactor-0.12.0.jar:0.12.0]
    at reactor.core.publisher.MonoCollectList.subscribe(MonoCollectList.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxSourceMonoFuseable.subscribe(FluxSourceMonoFuseable.java:38) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at org.springframework.http.server.reactive.ChannelSendOperator.subscribe(ChannelSendOperator.java:74) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1069) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1626) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapInner.onSubscribe(MonoFlatMap.java:230) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:271) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:803) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:1626) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1440) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1314) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:210) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:128) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:61) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.Mono.subscribe(Mono.java:3080) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:167) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:70) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:380) ~[reactor-netty-0.7.5.RELEASE.jar:0.7.5.RELEASE]
    at reactor.ipc.netty.http.server.HttpServerOperations.onHandlerStart(HttpServerOperations.java:397) ~[reactor-netty-0.7.5.RELEASE.jar:0.7.5.RELEASE]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) [netty-common-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463) [netty-transport-4.1.22.Final.jar:4.1.22.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) [netty-common-4.1.22.Final.jar:4.1.22.Final]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]
Caused by: java.lang.RuntimeException: fail
    at com.codependent.reactivegames.repository.GamesRepositoryImpl.findAll(GamesRepositoryImpl.kt:12) ~[classes/:na]
    at com.codependent.reactivegames.web.handler.ApiHandlers.getGames(ApiHandlers.kt:29) ~[classes/:na]
    at com.codependent.reactivegames.web.route.ApiRoutes$apiRouter$1$1$1.invoke(ApiRoutes.kt:14) ~[classes/:na]
    at com.codependent.reactivegames.web.route.ApiRoutes$apiRouter$1$1$1.invoke(ApiRoutes.kt:9) ~[classes/:na]
    at org.springframework.web.reactive.function.server.RouterFunctionDsl$GET$1.handle(RouterFunctionDsl.kt:155) ~[spring-webflux-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.reactive.function.server.support.HandlerFunctionAdapter.handle(HandlerFunctionAdapter.java:61) ~[spring-webflux-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.reactive.DispatcherHandler.invokeHandler(DispatcherHandler.java:168) ~[spring-webflux-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.web.reactive.DispatcherHandler.lambda$handle$1(DispatcherHandler.java:160) ~[spring-webflux-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) ~[reactor-core-3.1.5.RELEASE.jar:3.1.5.RELEASE]
    ... 37 common frames omitted

当电路处于打开状态时,最后一个呼叫的顺序,永远等待:

$ curl http://localhost:8081/api/v1/games
{"timestamp":"2018-03-14T12:44:57.145+0000","path":"/api/v1/games","status":500,"error":"Internal Server Error","message":"fail"}
$ curl http://localhost:8081/api/v1/games
{"timestamp":"2018-03-14T12:45:04.120+0000","path":"/api/v1/games","status":500,"error":"Internal Server Error","message":"fail"}
$ curl http://localhost:8081/api/v1/games
{"timestamp":"2018-03-14T12:45:05.649+0000","path":"/api/v1/games","status":500,"error":"Internal Server Error","message":"fail"}
$ curl http://localhost:8081/api/v1/games
{"timestamp":"2018-03-14T12:45:06.849+0000","path":"/api/v1/games","status":500,"error":"Internal Server Error","message":"fail"}
$ curl http://localhost:8081/api/v1/games
{"timestamp":"2018-03-14T12:45:07.824+0000","path":"/api/v1/games","status":500,"error":"Internal Server Error","message":"fail"}
$ curl http://localhost:8081/api/v1/games
...

1 个答案:

答案 0 :(得分:1)

问题1:

在订阅阶段触发错误时,弹性4j / reactor集成中存在错误。 (我打开了一个带有修复https://github.com/resilience4j/resilience4j/pull/213)的公关

解决方法

  • 使用Flux.error(RuntimeException("fail"), true)不会在订阅时触发错误,但会按要求
  • 添加一个自定义挂钩Hooks.onErrorDropped,它会丢弃错误而不是冒泡错误。

问题2:

您可以使用onErrorResume

之类的内容

fun getGames(serverRequest: ServerRequest): Mono<ServerResponse> { println("*********${circuitBreaker.state}") return ok().body( gamesRepository.findAll() .transform(CircuitBreakerOperator.of(circuitBreaker)) .onErrorResume(CircuitBreakerOpenException::class.java, { _ -> Flux.empty() }) , Game::class.java ) }