首页 > 解决方案 > 在 Mono 上重试似乎会生成一个无限循环

问题描述

我正在尝试学习 Reactor,并创建了以下示例:

  fun dbThingErrorSometimes() : Mono<String> {
        return if (Random.nextBoolean()){
            processDbResult(pooledClient.execute("SELECT * FROM product"))
        }else{
            Mono.error(RuntimeException("boom"))
        }
    }

然后我在哪里使用它(在控制器中):

 @RequestMapping("/dbpooledretry")
    @ResponseBody
    fun dbExamplePoolRetrying(): Mono<String> {
        return dbService.dbThingErrorSometimes()
                .retry()
    }

当它出现错误时,它会陷入无限循环(rest call 永远不会返回并且 cpu 会达到 100%)。为什么?

标签: spring-webfluxproject-reactor

解决方案


您的retry()方法只是重试由 . 返回的发布者dbService.dbThingErrorSometimes(),这可能是Mono.error(). dbService.dbThingErrorSometimes()永远不会被重新调用,它发出的发布者只会被重新订阅。

因此,如果它确实发出错误,那么重新订阅同一个错误发布者永远不会改变结果,因此你的无限循环。

相反,您可能希望每次重试时都Mono懒惰地重新调用- 您可以通过将该方法调用包装在.dbService.dbThingErrorSometimes()Mono.defer()


推荐阅读