带有非流应用程序/ json的Spring WebFlux Flux行为

我正在评估使用Spring Webflux,但我们必须支持期望使用application / json而不是application / stream +

json的客户端。我不清楚在需要application / json的客户端中,Spring WebFlux如何处理序列化Flux。

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

下面,我整理了一个示例控制器来演示我所看到的。当流是无限的并且产生application /

json时,什么都不会返回到浏览器。这似乎很合理,因为它可能正在等待流终止。当流是无限的并产生application / stream +

json时,我会按预期在浏览器中连续看到JSON对象。当Flux是有限的(例如100个元素)并且类型为application /

json时,它将一次按预期呈现。 问题是,它是否必须等待Flux终止才能进行序列化,是否会导致阻塞操作。 返回正常的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]

而使用JSON的有限对象仅使用一个线程。

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

回答:

对于流式mimetype(application/stream+json),Spring

WebFlux中默认配置的JSON编解码器将序列化为JSON,并在网络上刷新Flux输入的每个元素。当流无限或要在可用时将信息推送到客户端时,此行为很方便。请注意,这会降低性能,因为调用串行器并多次刷新会占用资源。

对于非流类型(application/json),在Spring

WebFlux中默认配置的JSON编解码器将序列化为JSON并一次性刷新到网络。它将缓存Flux<YourObject>在内存中,并在一次通过中将其序列化。这并不意味着操作正在阻塞,因为结果Flux<Databuffer>是以反应方式写入网络的。这里没有任何障碍。

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

在流传输的情况下,由于工作项在不同的时间间隔可用,因此更有可能由不同的工作线程处理事物。对于简单的JSON响应-

也可能由一个或多个线程处理:无论远程客户端是否慢,它都取决于有效负载大小。

以上是 带有非流应用程序/ json的Spring WebFlux Flux行为 的全部内容, 来源链接: utcz.com/qa/409965.html

回到顶部