Как повысить производительность в реактивном программировании с одноядерным процессором - PullRequest
0 голосов
/ 23 июня 2019

У меня есть приложение, которое подключается к стороннему сервису и возвращает результат клиенту.Внутри приложение делает запрос GET стороннему сервису и получает результат.Я использовал Reactor и реактивный код для масштабирования приложения при больших нагрузках.Это проект Spring Boot, который запускает встроенный Tomcat и использует Web Client (Reactive netty для отправки запросов третьей стороне).Почему-то загрузка ЦП и время отклика хуже, чем в режиме блокировки.Аппаратная настройка имеет single core , работающий в Kubernetes .

Проект настроен внутри Kubernetes и работает на одном модуле с одним ядром.Я пытался реагировать, но приложение намного медленнее и даже загрузка ЦП высока по сравнению с архитектурой блокировки.

 public Mono<ResponseEntity<?>> get(HttpServletRequest request)
   {
      return Mono.create ( callback -> {
         Mono<Response> response = Make HTTP GET Call using webClient.
         response.subscribe(response -> {
         callback.success(response);
         },error -> {
         callback.error(error);
         }
       });
    }

С традиционным режимом блокировки я рад видеть более высокую производительность и уменьшенную загрузку ЦП при сопоставлении с реактивным подходом.Что может быть причиной этого неравенства?Это из-за переключения контекста, поскольку есть только одно ядро?Если да, как мы можем достичь лучшей производительности благодаря одноядерной архитектуре?

Ответы [ 2 ]

2 голосов
/ 23 июня 2019

Я не очень понимаю, почему вы подписываетесь посередине, чтобы извлечь ответ. Подписка, я думаю, является дорогостоящим процессом и должна выполняться только один раз вызывающим клиентом.

Это пример того, как я мог бы сделать это, используя метод doOnError для обработки ошибок и отображения ответа.

public Mono<Foo> bar() {
    return client.get()
            .uri("/something")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .flatMap(response -> response.bodyToMono(Foo.class))

}

public Mono<Bar> foo() {
    return bar()
        .flatMap(stuff -> {
         return // Map it here to something else that 
                // is getting returned to the calling client
        })
        .doOnError(FooBarException::new);
1 голос
/ 25 июня 2019

Во всей вашей реактивной цепочке должна быть только одна подписка.Задержка как можно больше - одна подписка в конце.Позвольте нам переписать ваш код:

public Mono<ResponseEntity<?>> get(HttpServletRequest request) {
      return Mono.just(requestObject)
                 .flatmap(a -> makeAsyncCall(a))
                 .doOnError(err -> doSomethingOnError());
}

Вы можете подписаться, где вы начинаете свою реактивную цепочку.Как правило, это будет контроллер.

Это будет:

Mono.just(request)
    .flatMap(request -> get(request))
    .subscribe(response -> setDeferredResult(response));

return deferredResult;
...