通过Spring Reactive WebClient同时流式传输请求/响应主体?

时间:2019-12-04 14:34:47

标签: java spring reactive-programming spring-webflux

在以下客户端与服务器的交互中,我看到一些奇怪的行为,我想知道我是否正在运行HTTP / 1.1语义,或者我的Reactive编程技能是否需要工作(或两者都需要)。

我正在尝试创建一个客户端-服务器交互,其中请求和响应主体都是长时间运行的数据流。

客户端是Spring Reactive WebClient,它在请求主体中发送无限流。它期望接收(并记录)无限结果。

Flux<Long> requests = Flux.interval(Duration.ofSeconds(2));

return WebClient.create()
        .post()
            .uri("/instructions")
            .contentType(MediaType.APPLICATION_STREAM_JSON)
            .body(requests, Long.class)
        .retrieve()
            .bodyToFlux(Object.class)
            .map(response -> {
                log.info("Received Response Object {}", response);
                return response;
            });

服务器是一个spring-boot-starter-webflux应用程序,带有路由处理程序,用于记录收到的请求对象并提供无限的结果流:

public Mono<ServerResponse> instructions(ServerRequest request) {
    // Log the request objects as they are received
    Flux<Object> requestStream = request.bodyToFlux(Object.class)
            .map(r -> {
                log.info("Received Request Object: {}", r);
                return r;
            });

    requestStream.subscribe();

    // Infinite stream of responses
    Flux<Long> responses = Flux.interval(Duration.ofSeconds(5));

    return ServerResponse.ok()
            .contentType(MediaType.APPLICATION_STREAM_JSON)
            .body(responses, Long.class);
}

运行上述代码时,服务器记录无限个请求对象流,但是客户端从不记录任何响应对象。

如果我通过执行以下操作来绑定请求流:Flux<Long> requests = Flux.interval(Duration.ofSeconds(2)).take(20);,则客户端将在收到所有请求后开始记录响应。

这里有什么问题? *反应式代码有什么问题吗? *这是HTTP / 1.1规范的一部分,在完全接收到请求正文之前不应该发送响应头吗?

1 个答案:

答案 0 :(得分:1)

看到这个问题:WebClient doesn't read response until request write is completed.

显然,基于Netty的WebClient仅在完成请求发送后才开始处理响应

Netty服务器的行为也可能类似(仅在完成读取请求正文后才开始发送响应),我不确定

有趣的是,基于Jetty的WebClient能够同时处理请求和响应