Является ли Spring webclient неблокирующим клиентом? - PullRequest
1 голос
/ 01 мая 2019

Я не понимаю, как работает реактивный веб-клиент. В нем говорится, что весенний веб-клиент является неблокирующим клиентом, но этот веб-клиент кажется ожидающим сигналом onComplete () от удаленного API, после чего он может обрабатывать каждый элемент, отправленный удаленным API. Я ожидаю, что веб-клиент может обрабатывать каждый элемент, когда onNext () запускается из целевого API

Я новичок в весеннем мире webflux. Я читал об этом, и он говорит, что использует Netty в качестве сервера по умолчанию. И это нетто с помощью eventloop. Чтобы понять, как это работает, я пытаюсь создать 2 небольших приложения: клиент и сервер. Серверное приложение возвращает простой поток с задержкой в ​​1 секунду для каждого элемента. Клиентское приложение, использующее веб-клиент для вызова удаленного API.

Сервер:

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

Клиент:

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

Вход с сервера:

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

Журнал от клиента:

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 секунды, а затем получит реальный результат. Как вы можете видеть, сервер запускает onNext () на 22: 44: 21.126 , и клиент получает результат на 22: 44: 24.159 . Поэтому я не понимаю, почему веб-клиент называется неблокирующим клиентом, если у него такое поведение.

1 Ответ

1 голос
/ 08 мая 2019

WebClient является неблокирующим в том смысле, что поток, отправляющий HTTP-запросы через WebClient, не блокируется операцией ввода-вывода.Когда ответ станет доступен, netty уведомит один из рабочих потоков и обработает ответ в соответствии с заданными вами операциями реактивного потока.

В вашем примере сервер будет ждать, пока все элементы потокадоступны (4 секунды), сериализуют их в массив JSON и отправляют обратно в виде одного HTTP-ответа.

Клиент ожидает этот единственный ответ, но ни один из его потоков не блокируется в течение этого периода.

Если вы хотите добиться эффекта потоковой передачи, вам нужно использовать другой тип контента или базовый протокол, такой как WebSockets.Извлеките следующую ветку SO о типе контента application/stream+json: Поведение Spring WebFlux Flux с не потоковым приложением / json

...