如何从WebFlux客户端正确耗尽/释放响应正文?

时间:2019-04-14 01:24:48

标签: java spring-webflux project-reactor

我正在使用Spring 5反应堆中的WebFlux HTTP Client访问外部REST服务。我想根据HTTP状态处理响应:

  1. 如果状态为2xx,我想返回带有反序列化响应正文的Mono

  2. 如果状态为404,我想删除响应正文并立即返回空Mono

  3. 对于其他任何状态,我想删除响应正文并使用MyBusinessException返回错误Mono。

我的代码如下:

webClient.get()
    .uri("/search")
    .syncBody(request)
    .exchange()
    .flatMap { response ->
        when {
            response.statusCode().is2xxSuccessful -> response.bodyToMono(MyResponse::class.java)
            response.statusCode() == NOT_FOUND -> Mono.empty()
            else -> MyBusinessException().toMono<MyResponse>()
        }
     }

我不想在不需要时浪费时间来接收和处理响应正文。 exchange()方法状态的JavaDoc

  

您必须始终使用响应的主体或实体方法之一,以确保释放资源。

如果我要耗尽响应主体并立即返回结果,该怎么做?

1 个答案:

答案 0 :(得分:1)

需要耗尽响应,以便可以将连接重用于以后的请求(即http keep-alive /持久连接)。

要返回一个空的Mono,该文本将在排空正文后完成(忽略错误):

// drain the body
response.body(BodyExtractors.toDataBuffers())
    // release DataBuffers
    .doOnNext(DataBufferUtils::release)
    // ignore errors
    .onErrorResume(exception -> Mono.empty())
    // return an empty Mono
    .then();

要返回立即完成的空Mono,并在后台异步消耗主体(忽略错误):

Mono.<Void>empty()
    .doOnSubscribe(s ->
        // drain the body
        response.body(BodyExtractors.toDataBuffers())
            // release DataBuffers
            .doOnNext(DataBufferUtils::release)
            // initiate drain on a separate Scheduler
            .subscribeOn(Schedulers.parallel())
            // subscribe, and ignore errors
            .subscribe())

我仍然建议第一种选择,因为它会立即释放资源,并且可能是WebClient开发人员在编写和记录其用法时所想到的。

我从未在生产系统中使用过第二个选项,因此请进行您自己的测试,以确保http连接池的行为符合预期。如果使用react-netty,则可以在reactor.netty.resources.PooledConnectionProvider上启用调试日志记录以比较这两种方法。