Spring @RestController вызывает большое количество запросов

Я реализую REST API, используя Spring Boot и @RestController с Java 8. Один из методов контроллера должен вызывать другую стороннюю службу REST API. Метод описан следующим образом (формат данных — JSON):

  1. Вызовите сторонний метод API, чтобы получить список кандидатов (каждый кандидат представлен в виде объекта с некоторой базовой информацией).
  2. Для каждого кандидата вызовите другой сторонний метод API, чтобы получить более подробную информацию о кандидате.
  3. Смешайте результаты, существенно обогащая все объекты-кандидаты из первого вызова.
  4. Вернуть список расширенных объектов-кандидатов.

Я планировал использовать @RestTemplate для всех вызовов стороннего API. Что меня беспокоит, так это то, что для большого количества кандидатов (скажем, 500-1000) это станет огромным узким местом в производительности, если оно будет реализовано блокирующим образом. Я не совсем уверен, какой подход рекомендуется для достижения наилучшей производительности. Как я могу масштабировать это, чтобы несколько пользователей могли одновременно получать доступ к моему API?


person Web User    schedule 18.11.2016    source источник


Ответы (4)


Ваш вопрос ОЧЕНЬ широк, и я не думаю, что кто-то сможет дать вам подробный ответ, но:

  1. Ваш случай кажется идеальным вариантом использования RxJava: поток кандидатов, который трансформируется путем добавления дополнительной информации из других источников — и все это делается асинхронно.

  2. Я бы пропустил RestTemplate и выбрал Retrofit2 вместе с их потрясающей интеграцией RxJava. См. этот базовый руководство1 и tutorial2.

  3. 1000 записей — это немного, но это также зависит от производительности нижестоящих сервисов. Вам нужно будет проверить это на себе.

  4. Если вы хотите узнать больше о RxJava, есть несколько отличных документов в Интернете, а также новая потрясающая книга Томаша Нуркевича и Бена Кристенсена.

Удачи!

person Rafal G.    schedule 18.11.2016
comment
Спасибо! Это очень поучительный пост; Я пройдусь по учебникам и узнаю о RxJava и Retrofit2. Может ли это вписаться в среду Spring Boot? Я наткнулся на этот post, который, кажется, ручается за интеграцию, но мне интересно, есть ли у вас собственный опыт в этом отношении. - person Web User; 18.11.2016
comment
Да, конечно. Retrofit можно легко использовать с Spring Boot. Вам просто нужно создать экземпляр клиента OkHttp3, а затем использовать его для создания экземпляра клиента Retrofit2 REST. Этот клиент должен быть Spring Bean - тогда это просто типичный Spring DI. Те tutorisls охватывают это хорошо. - person Rafal G.; 19.11.2016

Рафаль уже дал отличный ответ. Я хотел бы добавить свои 2 цента. Ваш случай кажется идеальным вариантом использования неблокирующего. RxJava — это всего лишь одна из реализаций неблокирующего реактивного программирования. Вы можете добиться того же, используя другой стек технологий, например, akka или spring boot с netty или undertow.

Это пример того, как мы можем выполнять реактивное программирование с помощью Spring Boot. https://spring.io/blog/2016/07/28/reactive-programming-with-spring-5-0-m1 имейте в виду, что он все еще находится в экспериментальном состоянии. Реактивные потоки будут встроены в Java 9

person so-random-dude    schedule 19.11.2016
comment
Спасибо, что поручились за первый ответ, а также указали мне на весеннюю загрузку, которую я уже использую. Много приятного чтения в эти выходные. - person Web User; 19.11.2016

Ваш сервер приложений будет управлять пулом потоков, поэтому на вашу конечную точку может одновременно поступать множество запросов. Если ваш пул потоков не имеет размера 1, несколько клиентов смогут одновременно использовать ваш API.

Дополнительные пояснения см. здесь: Spring MVC Rest Services - количество потоков (Экземпляры контроллера)

См. здесь пример настройки размера пула потоков: Maximum ( клиентский запрос) размер пула потоков весной

Чтобы повысить производительность при отправке запросов к внешним службам, я хотел бы посмотреть, можете ли вы делать пакетные запросы (несколько кандидатов одновременно), чтобы уменьшить общее количество запросов, которые вы делаете.

person Adam    schedule 18.11.2016
comment
Я не могу делать пакетные запросы, потому что внешние сервисы не поддерживают несколько кандидатов одновременно :-( Но я обязательно посмотрю на оптимизацию размера пула потоков и проведу некоторые тесты производительности. Вскоре у меня должны быть некоторые цифры. - person Web User; 18.11.2016

Ответ на старую тему. Ниже приведены некоторые из вещей, которые можно использовать.

  1. Используйте AsyncHttp вместо RestTemplate.
  2. Настройте отдельный пул потоков (Executor Service) для выполнения внешних вызовов.
  3. По возможности вызывайте внешний API с помощью Java 8 CompletableFuture.supplyAsync(() -> externalCall(),executorService). Как для первого стороннего вызова, так и для вложенного вызова.
  4. Верните смешанный объект, обернутый с помощью CompletableFuture, в контроллер.
person VimalKumar    schedule 25.01.2021