Is Spring webclient non-blocking client?

只谈情不闲聊 提交于 2021-02-07 22:37:08

问题


I don't understand reactive webclient works. It says that spring webclient is non-blocking client, but this webclient seems waiting signal onComplete() from remote api, then it can process each item that emitted from the remote api. I'm expecting that webclient can process each item when onNext() is fired from the target api

I'm new in the spring webflux worlds. I read about it and it says it uses netty as default server. And this netty using eventloop. So to understand how it works I try to create 2 small apps, client and server. Server app only return simple flux with delay 1 second each item. Client app using webclient to call remote api.

Server:

@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 : ");
}

Client:

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();
}

Log from server:

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()

Log from client:

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()

I'm expecting that client won't wait for 4 seconds then get the actual result. As you can see that server start emit onNext() on 22:44:21.126, and client get result on 22:44:24.159. So I don't understand why webclient is called non-blocking client if it has this behaviour.


回答1:


The WebClient is non-blocking in a sense that the thread sending HTTP requests through the WebClient is not blocked by the IO operation. When the response is available, netty will notify one of the worker threads and it will process the response according to the reactive stream operations that you defined.

In your example the server will wait until all the elements in a Flux are available (4 seconds), serialize them to the JSON array, and send it back in a single HTTP response.

The client waits for this single response, but non of its threads are blocked during this period.

If you want to achieve the streaming effect, you need to leverage different content-type or the underlying protocol like WebSockets. Check-out the following SO thread about the application/stream+json content-type: Spring WebFlux Flux behavior with non streaming application/json



来源:https://stackoverflow.com/questions/55939068/is-spring-webclient-non-blocking-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!