Spring WebClient:使用 WebFlux.fn +reactor-addons 重试

2023-12-24

我正在尝试添加条件重试WebClient使用 Kotlin 协程 + WebFlux.fn +reactor-addons:

suspend fun ClientResponse.asResponse(): ServerResponse =
    status(statusCode())
        .headers { headerConsumer -> headerConsumer.addAll(headers().asHttpHeaders()) }
        .body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)
        .retryWhen { 
            Retry.onlyIf { ctx: RetryContext<Throwable> -> (ctx.exception() as? WebClientResponseException)?.statusCode in retryableErrorCodes }
                .exponentialBackoff(ofSeconds(1), ofSeconds(5))
                .retryMax(3)
                .doOnRetry { log.error("Retry for {}", it.exception()) }
        )
        .awaitSingle()

还在重试之前添加一个条件

if (statusCode().isError) {
        body(
            BodyInserters.fromPublisher(
                Mono.error(StatusCodeError(status = statusCode())),
                StatusCodeException::class.java
            )
        )
    } else {
        body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)
    }

调用看起来像:

suspend fun request(): ServerResponse =
           webClient/*...*/
                    .awaitExchange()
                    .asResponse()

This spring webclient:在特定错误上进行回退重试 https://stackoverflow.com/questions/58520919/spring-webclient-retry-with-backoff-on-specific-error/58521233#58521233给了我回答问题的提示:

.awaitExchange()返回ClientResponse并不是Mono<ClientReponse>这意味着我的重试正在执行bodyToMono而不是操作exchange().

解决方案现在看起来像

suspend fun Mono<ClientResponse>.asResponse(): ServerResponse =
    flatMap {
        if (it.statusCode().isError) {
            Mono.error(StatusCodeException(status = it.statusCode()))
        } else {
            it.asResponse()
        }
    }.retryWhen(
        Retry.onlyIf { ctx: RetryContext<Throwable> ->
            (ctx.exception() as? StatusCodeException)?.shouldRetry() ?: false
        }
            .exponentialBackoff(ofSeconds(1), ofSeconds(5))
            .retryMax(3)
            .doOnRetry { log.error { it.exception() } }
    ).awaitSingle()

private fun ClientResponse.asResponse(): Mono<ServerResponse> =
    status(statusCode())
        .headers { headerConsumer -> headerConsumer.addAll(headers().asHttpHeaders()) }
        .body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring WebClient:使用 WebFlux.fn +reactor-addons 重试 的相关文章

随机推荐

  • 防止delayed_job后台作业在单个服务器上消耗过多的CPU

    我的 Rails 应用程序有许多任务被卸载到后台进程中 例如调整图像大小和上传到 S3 我在用着延迟作业 http github com collectiveidea delayed job tree master来管理这些流程 这些过程
  • Java:观察目录以移动大文件

    我一直在编写一个程序来监视目录 当在其中创建文件时 它会更改名称并将它们移动到新目录 在我的第一个实现中 我使用了 Java 的 Watch Service API 当我测试 1kb 文件时 它运行良好 出现的问题是 实际上创建的文件大小在
  • 如何在新行而不是主行中呈现 CKEditor5 工具栏按钮?

    我从源代码将 CKEditor5 集成到我的 create React 应用程序中 现在 我想在工具栏的新行中渲染溢出的按钮 但它们显示在单独的菜单项中 如何在新行而不是主行中显示按钮 这是我的配置 ClassicEditor defaul
  • 无法在 git 中复制和粘贴 - macos

    有谁知道如何使用 macOS 复制并粘贴 git 吗 我无法在左下窗格中选择 突出显示和复制其中的文本 更改 Thanks 我可以通过按以下命令从 gitk 复制 fn C
  • 如何从 TreeNode.FullPath 数据获取实际的树节点?

    我想存储 TreeNode FullPath 中的一些数据 然后我想重新扩展到目前为止的所有内容 有简单的方法吗 多谢 您可以将其编写为扩展方法TreeNodeCollection using System using System Lin
  • 仅显示 ISO 8601 时间戳的 12 小时时间格式

    所以我想在我的 iOS 应用程序的标签中显示从服务器传递的时间 但我在尝试找出如何设置正确的 NSDateFormatter 时遇到了麻烦 例如 我以这种格式从服务器获取此时间戳 2013 02 27T18 15 00 0800 我基本上想
  • 如何获得英文版的Win32Exception?

    我正在努力得到所有Exception消息都是英文的 无论我的程序运行在什么语言上 我已经使用以下帖子中的答案设法获得了几乎所有英文异常消息 异常消息是英文的吗 https stackoverflow com questions 209133
  • Flexbox 容器中的省略号[重复]

    这个问题在这里已经有答案了 自从最新 版本的 Firefox Nightly 35 0a1 以来 我一直遇到一个问题text overflow ellipsis在 Flexbox 容器内flex direction row 每列宽 50 D
  • WebGL GLSL 片段着色器在 iOS 上不起作用

    我正在使用经典柏林噪声 vec3 函数here https gist github com patriciogonzalezvivo 670c22f3966e662d2f83 classic perlin noise 当我在 MacBook
  • Windows 8 低功耗蓝牙 API 示例

    有没有人找到关于如何使用 C C 在 Windows 8 上发现 连接和断开 BLE 设备的好示例 我不确定如何获取与 蓝牙低能耗功能 API 一起使用的设备句柄http msdn microsoft com en us library w
  • 如何在codeigniter中显示电子邮件中的图像?

    this gt load gt library upload this gt load gt library email this gt email gt set newline r n this gt email gt from emai
  • 为什么 DapperRow.GetType() 返回 null?

    据我所知 Object GetType 永远不应该返回 null 相关讨论 https stackoverflow com questions 2201007 can object gettype ever return null Dapp
  • ZF + Doctrine2 phpUnit 错误:PDOExeption:您无法序列化或反序列化 PDO 实例

    我正在使用 DynamicGuys Doctrine2 集成到 zend 框架中 https github com dynamicguy zf1doctrine2 它有效 但如果我想用 phpUnit 进行测试 我会收到此错误 PDOExe
  • 无法在异步模块中使用“map”功能

    我正在使用node js 异步 模块并且需要使用 map 方法 基本上我有一个包含其他数组的数组 内部数组包含 2 个元素 类型和图像文件名 var arr0 var arr1 type1 image1 jpg jsonArr push o
  • QListWidget中的InternalMove使项目消失

    我正在尝试在树小部件内进行拖放操作 以便能够在该小部件内移动项目 我已经设法使项目可拖动 但是当我释放鼠标按钮时 该项目就会消失 为了缩小范围 我尝试了以下示例 取自此处的另一篇文章 它与 Windows 7 上的 Qt 5 4 中的树小部
  • Automapper 自定义值解析器重用多种类型

    我有一个项目 我试图使用 AutoMapper 从多个类进行映射 每个类中都有一些属性 我想使用一些自定义逻辑将源值解析到目标 我尝试使用 AutoMapper 文档中记录的自定义解析器方法 这是我的代码 public class Cust
  • Chrome 中的同步控制台日志记录

    是否可以同步记录到控制台 我经常遇到代码执行比转储结构更快的情况 这解决了输出已更改的对象的问题 我当然可以使用调试器浏览代码 进行单元测试等 通常很方便console log只是为了大致了解正在发生的事情 您可以在将对象传递给之前创建该对
  • 将 React Element 的字符串值的一部分设为粗体

    我在我的文件中定义了变量 var text The start of string b this state isTrue Bolded Also Bolded b the end of string 该字符串被传递给 React 元素 s
  • 构建批量插入语句powershell到sql

    我有一个 powershell 脚本 它从特定目录开始递归地写入每个文件及其属性 这可行 但目录可能包含多达 1 000 000 个文件 我想要做的是以每个事务 1000 次插入的方式对它们进行批处理 PS原图如下 server Datab
  • Spring WebClient:使用 WebFlux.fn +reactor-addons 重试

    我正在尝试添加条件重试WebClient使用 Kotlin 协程 WebFlux fn reactor addons suspend fun ClientResponse asResponse ServerResponse status s