Is Spring webclient non-blocking client?
我不了解反应式Webclient的工作原理。它说spring webclient是非阻塞客户端,但是这个webclient似乎正在等待来自远程api的onComplete()信号,然后它可以处理从远程api发出的每个项目。
我期望从目标api触发onNext()时,webclient可以处理每个项目
我是Springwebflux领域的新手。我读到它,并说它使用netty作为默认服务器。而这个netty使用了eventloop。因此,为了解其工作原理,我尝试创建2个小型应用程序(客户端和服务器)。
服务器应用仅返回简单通量,每项延迟1秒。
使用webclient调用远程api的客户端应用。
服务器:
1 2 3 4 5 6 7 8 | @GetMapping(ITEM_END_POINT_V1) public Flux<Item> getAllItems(){ return Flux.just(new Item(null,"Samsung TV", 399.99), new Item(null,"LG TV", 329.99), new Item(null,"Apple Watch", 349.99), new Item("ABC","Beats HeadPhones", 149.99)).delayElements(Duration.ofSeconds(1)).log("Item :"); } |
客户:
1 2 3 4 5 6 7 8 | WebClient webClient = WebClient.create("http://localhost:8080"); @GetMapping("/client/retrieve") public Flux<Item> getAllItemsUsingRetrieve() { return webClient.get().uri("/v1/items") .retrieve() .bodyToFlux(Item.class).log(); } |
来自服务器的日志:
1 2 3 4 5 6 7 | 2019-05-01 22:44:20.121 INFO 19644 --- [ctor-http-nio-2] Item : : onSubscribe(FluxConcatMap.ConcatMapImmediate) 2019-05-01 22:44:20.122 INFO 19644 --- [ctor-http-nio-2] Item : : request(unbounded) 2019-05-01 22:44:21.126 INFO 19644 --- [ parallel-1] Item : : onNext(Item(id=null, description=Samsung TV, price=399.99)) 2019-05-01 22:44:22.129 INFO 19644 --- [ parallel-2] Item : : onNext(Item(id=null, description=LG TV, price=329.99)) 2019-05-01 22:44:23.130 INFO 19644 --- [ parallel-3] Item : : onNext(Item(id=null, description=Apple Watch, price=349.99)) 2019-05-01 22:44:24.131 INFO 19644 --- [ parallel-4] Item : : onNext(Item(id=ABC, description=Beats HeadPhones, price=149.99)) 2019-05-01 22:44:24.132 INFO 19644 --- [ parallel-4] Item : : onComplete() |
来自客户端的日志:
1 2 3 4 5 6 7 8 9 | 2019-05-01 22:44:19.934 INFO 24164 --- [ctor-http-nio-2] reactor.Flux.MonoFlatMapMany.1 : onSubscribe(MonoFlatMapMany.FlatMapManyMain) 2019-05-01 22:44:19.936 INFO 24164 --- [ctor-http-nio-2] reactor.Flux.MonoFlatMapMany.1 : request(unbounded) 2019-05-01 22:44:19.940 TRACE 24164 --- [ctor-http-nio-2] o.s.w.r.f.client.ExchangeFunctions : [7e73de5c] HTTP GET http://localhost:8080/v1/items, headers={} 2019-05-01 22:44:24.159 TRACE 24164 --- [ctor-http-nio-6] o.s.w.r.f.client.ExchangeFunctions : [7e73de5c] Response 200 OK, headers={masked} 2019-05-01 22:44:24.204 INFO 24164 --- [ctor-http-nio-6] reactor.Flux.MonoFlatMapMany.1 : onNext(Item(id=null, description=Samsung TV, price=399.99)) 2019-05-01 22:44:24.204 INFO 24164 --- [ctor-http-nio-6] reactor.Flux.MonoFlatMapMany.1 : onNext(Item(id=null, description=LG TV, price=329.99)) 2019-05-01 22:44:24.204 INFO 24164 --- [ctor-http-nio-6] reactor.Flux.MonoFlatMapMany.1 : onNext(Item(id=null, description=Apple Watch, price=349.99)) 2019-05-01 22:44:24.204 INFO 24164 --- [ctor-http-nio-6] reactor.Flux.MonoFlatMapMany.1 : onNext(Item(id=ABC, description=Beats HeadPhones, price=149.99)) 2019-05-01 22:44:24.205 INFO 24164 --- [ctor-http-nio-6] reactor.Flux.MonoFlatMapMany.1 : onComplete() |
我希望客户不会等待4秒钟,然后会得到实际的结果。
如您所见,服务器在22:44:21.126开始发出onNext(),而客户端在22:44:24.159获得结果。
所以我不明白为什么Webclient具有这种行为就被称为非阻塞客户端。
WebClient是非阻塞的,即通过IO操作不会阻塞通过WebClient发送HTTP请求的线程。
当响应可用时,netty将通知工作线程之一,它将根据您定义的响应流操作来处理响应。
在您的示例中,服务器将等待,直到Flux中的所有元素都可用(4秒钟),将它们序列化为JSON数组,然后在单个HTTP响应中将其发送回去。
客户端等待该单个响应,但在此期间未阻止其所有线程。
如果要实现流式传输效果,则需要利用不同的内容类型或基础协议,例如WebSockets。
签出有关
带有非流应用程序/ json的Spring WebFlux Flux行为