当前位置: 首页 > 知识库问答 >
问题:

使用非流式应用程序/JSON的Spring WebFlux流量行为

上官琦
2023-03-14

我正在评估使用Spring Webflux,但我们必须支持期望Application/JSON,而不是Application/Stream+JSON的客户机。我不清楚Spring WebFlux如何在需要Application/JSON的客户机的情况下处理Flux的序列化。

如果一个Flux序列化为application/json,而不是application/stream+json,这是一个阻塞操作吗?

下面我用一个示例控制器来演示我所看到的东西。当流是无限的并且产生Application/JSON时,不会向浏览器返回任何东西。这似乎是合理的,因为它可能正在等待流终止。当流是无限的并且生成Application/stream+JSON时,我会像预期的那样在浏览器中连续看到JSON对象。当流量是有限的,比如100个元素,并且类型是application/json时,它会一次呈现出预期的效果。问题是,在序列化之前,它是否必须等待通量终止,并且这是否会导致阻塞操作。当返回正常的Application/JSON时,使用Flux对性能和可伸缩性有什么影响?

@RestController
public class ReactiveController {

    /* Note: In the browser this sits forever and never renders */
    @GetMapping(path = "/nonStreaming", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Person> getPeopleNonStreaming() {
        return Flux.interval(Duration.ofMillis(100))
                .map(tick -> new Person("Dude", "Dude", tick));
    }

    /* Note: This renders in the browser in chunks forever */
    @GetMapping(path = "/streaming", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Flux<Person> getPeopleStreaming() {
        return Flux.interval(Duration.ofMillis(100))
                .map(tick -> new Person("Dude", "Dude", tick));
    }

    /* Note: This returns, but I can't tell if it is done in a non blocking manner. It
     * appears to gather everything before serializing. */
    @GetMapping(path = "/finiteFlux", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Person> finiteFlux() {
        return Flux.range(0, 100)
                .map(tick -> new Person("Dude", "Dude", tick));
    }
}

更新:

我在下面添加了其他日志记录信息:

2019-02-13 16:53:07.363 DEBUG 3416 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [dac80fd4] HTTP GET "/streaming"
2019-02-13 16:53:07.384 DEBUG 3416 --- [ctor-http-nio-2] s.w.r.r.m.a.RequestMappingHandlerMapping : [dac80fd4] Mapped to public reactor.core.publisher.Flux<io.jkratz.reactivedemo.Person> io.jkratz.reactivedemo.ReactiveController.getPeopleStreaming()
2019-02-13 16:53:07.398 DEBUG 3416 --- [ctor-http-nio-2] o.s.w.r.r.m.a.ResponseBodyResultHandler  : Using 'application/stream+json;q=0.8' given [text/html, application/xhtml+xml, image/webp, image/apng, application/xml;q=0.9, */*;q=0.8] and supported [application/stream+json]
2019-02-13 16:53:07.398 DEBUG 3416 --- [ctor-http-nio-2] o.s.w.r.r.m.a.ResponseBodyResultHandler  : [dac80fd4] 0..N [io.jkratz.reactivedemo.Person]
2019-02-13 16:53:07.532 DEBUG 3416 --- [     parallel-1] o.s.http.codec.json.Jackson2JsonEncoder  : [dac80fd4] Encoding [io.jkratz.reactivedemo.Person@6b3e843d]
2019-02-13 16:53:07.566 DEBUG 3416 --- [ctor-http-nio-2] r.n.channel.ChannelOperationsHandler     : [id: 0xdac80fd4, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52398] Writing object DefaultHttpResponse(decodeResult: success, version: HTTP/1.1)
HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/stream+json;q=0.8;charset=UTF-8
2019-02-13 16:53:07.591 DEBUG 3416 --- [ctor-http-nio-2] r.n.channel.ChannelOperationsHandler     : [id: 0xdac80fd4, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52398] Writing object 
2019-02-13 16:53:07.629 DEBUG 3416 --- [     parallel-1] o.s.http.codec.json.Jackson2JsonEncoder  : [dac80fd4] Encoding [io.jkratz.reactivedemo.Person@217d62db]
2019-02-13 16:53:07.630 DEBUG 3416 --- [ctor-http-nio-2] r.n.channel.ChannelOperationsHandler     : [id: 0xdac80fd4, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52398] Writing object 
2019-02-13 16:53:07.732 DEBUG 3416 --- [     parallel-1] o.s.http.codec.json.Jackson2JsonEncoder  : [dac80fd4] Encoding [io.jkratz.reactivedemo.Person@741c0c88]
2019-02-13 16:53:07.732 DEBUG 3416 --- [ctor-http-nio-2] r.n.channel.ChannelOperationsHandler     : [id: 0xdac80fd4, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52398] Writing object 
2019-02-13 16:53:07.832 DEBUG 3416 --- [     parallel-1] o.s.http.codec.json.Jackson2JsonEncoder  : [dac80fd4] Encoding [io.jkratz.reactivedemo.Person@7b8532e5]
2019-02-13 16:55:34.431 DEBUG 3416 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [5b048f46] HTTP GET "/finiteFlux"
2019-02-13 16:55:34.432 DEBUG 3416 --- [ctor-http-nio-3] s.w.r.r.m.a.RequestMappingHandlerMapping : [5b048f46] Mapped to public reactor.core.publisher.Flux<io.jkratz.reactivedemo.Person> io.jkratz.reactivedemo.ReactiveController.finiteFlux()
2019-02-13 16:55:34.434 DEBUG 3416 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler  : Using 'application/json;q=0.8' given [text/html, application/xhtml+xml, image/webp, image/apng, application/xml;q=0.9, */*;q=0.8] and supported [application/json]
2019-02-13 16:55:34.435 DEBUG 3416 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler  : [5b048f46] 0..N [io.jkratz.reactivedemo.Person]
2019-02-13 16:55:34.439 DEBUG 3416 --- [ctor-http-nio-3] o.s.http.codec.json.Jackson2JsonEncoder  : [5b048f46] Encoding [[io.jkratz.reactivedemo.Person@425c8296, io.jkratz.reactivedemo.Person@22ae73df, io.jkratz.reactived (truncated)...]
2019-02-13 16:55:34.448 DEBUG 3416 --- [ctor-http-nio-3] r.n.channel.ChannelOperationsHandler     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] Writing object DefaultHttpResponse(decodeResult: success, version: HTTP/1.1)
HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/json;q=0.8;charset=UTF-8
2019-02-13 16:55:34.448 DEBUG 3416 --- [ctor-http-nio-3] r.n.channel.ChannelOperationsHandler     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] Writing object 
2019-02-13 16:55:34.450 DEBUG 3416 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [5b048f46] Completed 200 OK
2019-02-13 16:55:34.450 DEBUG 3416 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] Last HTTP response frame
2019-02-13 16:55:34.450 DEBUG 3416 --- [ctor-http-nio-3] r.n.channel.ChannelOperationsHandler     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] Writing object EmptyLastHttpContent
2019-02-13 16:55:34.450 DEBUG 3416 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] Decreasing pending responses, now 0
2019-02-13 16:55:34.451 DEBUG 3416 --- [ctor-http-nio-3] r.n.channel.ChannelOperationsHandler     : [id: 0x5b048f46, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:52991] No ChannelOperation attached. Dropping: EmptyLastHttpContent

共有1个答案

南宫凯康
2023-03-14

在流式mimetype(application/stream+JSON)的情况下,在Spring WebFlux中默认配置的JSON编解码器将序列化为JSON,并在网络上刷新flux输入的每个元素。当流是无限大的时候,或者当您想要在信息可用的时候将其推送到客户机时,这种行为非常方便。请注意,这会带来性能代价,因为调用序列化程序并多次刷新会占用资源。

在非流类型(application/JSON)的情况下,在Spring WebFlux中默认配置的JSON编解码器将序列化为JSON,并一次性刷新到网络。它将在内存中缓冲通量 并在一次传递中序列化它。这并不意味着操作是阻塞的,因为生成的flux 是以对网络反应的方式编写的。这里没有东西挡住。

这只是“数据流化和使用更多资源”与“缓冲和更高效地使用资源”之间的折衷。

在流式处理的情况下,事情更有可能由不同的工作线程处理,因为工作项以不同的时间间隔可用。在简单JSON响应的情况下--它也可能由一个或多个线程处理:这取决于有效负载大小,如果远程客户机慢或不慢。

 类似资料:
  • 问题内容: 我正在评估使用Spring Webflux,但我们必须支持期望使用application / json而不是application / stream + json的客户端。我不清楚在需要application / json的客户端中,Spring WebFlux如何处理序列化Flux。 如果将Flux序列化为application / json而不是application / stre

  • 下图说明数据流如何贯穿整个系统: index.php 作为前端控制器,初始化运行 CodeIgniter 所需要的基本资源。 Router 检查 HTTP 请求,以确定谁来处理请求。 如果缓存(Cache)文件存在,它将绕过通常的系统执行顺序,被直接发送给浏览器。 安全(Security)。应用程序控制器(Application Controller)装载之前,HTTP 请求和任何用户提交的数据将

  • 下图说明了整个系统的数据流程: index.php 文件作为前端控制器,初始化运行 CodeIgniter 所需的基本资源; Router 检查 HTTP 请求,以确定如何处理该请求; 如果存在缓存文件,将直接输出到浏览器,不用走下面正常的系统流程; 在加载应用程序控制器之前,对 HTTP 请求以及任何用户提交的数据进行安全检查; 控制器加载模型、核心类库、辅助函数以及其他所有处理请求所需的资源;

  • 我能以某种方式截获来自应用程序的绝对所有流量吗?我应该做什么来做到这一点?提前谢谢你)

  • 我有一个反应式核心WebClient要发布到给定的endpoint。有效负载是对象的流量,内容类型是application/stream json flux jobFlux=flux。只是(新工作); 在服务器端,我尝试了Spring控制器样式和Spring Web反应式FunctionHandler,以使用流量负载处理上述调用的负载。 当实例化一个新对象时,域类创建和标识: 仓库目前只是一个存根

  • 我们已经构建了一个Flink应用程序来处理来自动觉流的数据。应用程序的执行流程包含基于注册类型过滤数据、基于事件时间戳分配水印的基本操作,以及应用于5分钟数据窗口的映射、处理和聚合功能,如下所示: 我的水印分配程序的参考代码: 现在,这个应用程序的性能很好(在几秒钟内的延迟方面),早就有了。然而,最近在上游系统post中发生了变化,其中Kinesis流中的数据以突发方式发布到流中(每天仅2-3小时