Обработка нескольких запросов одновременно

У меня есть класс обслуживания

    @Path("/")
     public class ABC {
      @Path(/process/{param})
      public String processRequest(@PathParam("param") String param){
        Thread t = new Thread(()->{
         // Do some processing with the param parmeter
          System.out.println("Processing started for -> "+ param);
          //Do many more things
          //DB transactions,etc.
           });
          t.start();
          return "Your request will be processed";
        }
}

Я принимаю какой-то параметр и начинаю обрабатывать его в новом потоке, и в то же время, чтобы он завершил обработку в течение 30 секунд, я разрываю свое соединение с клиентом, подтверждая его, что его запрос будет обработан.

Он работает нормально и до сих пор без проблем. В настоящее время он может обрабатывать более 5k запросов. Проблема начинается, когда одновременно поступает много запросов, может быть, более 50 КБ, поэтому мое приложение создает новый поток для каждого нового запроса, который заставляет приложение выделять много памяти, а также иногда приводит к исчерпанию памяти JVM.

Есть ли другой способ, с помощью которого я могу немедленно начать обработку, не беспокоясь о количестве запросов, и обработать все запросы в течение 30 секунд, а также ограничить количество активных рабочих потоков.

Один из способов, который я нашел, - это реализация «производитель-потребитель», в которой я могу принимать все запросы и одновременно передавать их производителям, а мои потребители забирают запрос и начинают его обрабатывать. Для этой реализации мне нужно указать максимальное количество запросов, которое может быть принятым производителем (Пример: 100000) и ни одним из потребителей, которые могут обработать запрос (Пример: 1000), так что только 1000 потоков активны и обрабатываются один за другим, но проблема с этим подходом заключается в том, что если любой из потребителей (работающих ) thread, если блокируется по какой-то причине и если он не освобожден, то для обработки запроса остаются только оставшиеся разблокированные потоки, а количество входящих запросов в производителях постоянно увеличивается. Только увеличение количества потребителей создает больше рабочего потока, но в то же время может быть много заблокированных потоков, обрабатывающих задачу.

Пожалуйста, дайте мне знать о любом другом подходе, с помощью которого я могу это сделать.

Примечание: весь запрос должен быть обработан в течение 30 секунд, и если это невозможно, то он не соответствует критериям успеха.

Вам нужен ExecutorService.

Kayaman 23.05.2018 12:06

Не могли бы вы дать мне ссылку, чтобы реализовать его, а также его преимущества

Ahmad Qureshi 23.05.2018 12:07

Что произойдет, если ваша система отключится или выйдет из строя при обработке некоторых из этих запросов? Можете ли вы позволить себе их потерять? В противном случае правильным решением, вероятно, будет очередь (например, Rabbit), а затем прослушиватель, настроенный с несколькими потребителями (или потоками), обрабатывающими запросы. По крайней мере, так вы никогда не потеряете запрос, и он переживет отключения или сбои.

Edwin Dalorzo 23.05.2018 12:10

Для какого-то типа запроса это нормально, он терпит неудачу, но некоторые из них имеют решающее значение, поскольку в нем задействованы деньги клиентов, и если это не удастся, потребуется ручное вмешательство, что приведет к ненужным задержкам, я думаю, я должен попробовать кролика

Ahmad Qureshi 23.05.2018 12:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
1 588
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать систему очередей, чтобы помещать запросы в очередь и подтверждать клиенту об обработке, а позже вы можете обрабатывать очередь.

Производитель-Потребитель - это похожая реализация, верно? Производитель - это очередь и потребитель, обрабатывающий запрос в очереди.

Ahmad Qureshi 23.05.2018 12:16
Ответ принят как подходящий

Вероятно, вам нужен механизм очередей, например RabbitMq.

Ваше приложение будет работать так:

request -> push to queue -> return ACK to client

queue -> worker threads.

Скорость потребителя queue определяется скоростью ваших рабочих потоков, поэтому вы никогда не исчерпаете свою систему.

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

Не могли бы вы предоставить какую-либо ссылку на него ?? Спасибо :)

Ahmad Qureshi 23.05.2018 12:30

Ссылка на какую часть? Все они базовые

Mạnh Quyết Nguyễn 23.05.2018 12:31

Любой учебник как таковой?

Ahmad Qureshi 23.05.2018 12:33

Практически все, что касается производителя-потребителя, использующего, чувак, RabbitMQ.

Mạnh Quyết Nguyễn 23.05.2018 12:49

Вот пример на официальная страница. Если вы используете фреймворк, есть вероятность, что какой-то код конфигурации / шаблонного кода уже обрабатывается в библиотеке, например, spring-rabbit

Mạnh Quyết Nguyễn 23.05.2018 12:51

Большое спасибо

Ahmad Qureshi 23.05.2018 14:26

Вам нужно обслуживать большое количество (может быть одновременных) запросов, а также контролировать количество порожденных потоков (максимальное ограничение на количество потоков). Лучше всего использовать ExecuterService, который является своего рода пулом управляемых потоков, где вы можете указать размер пула потоков и отправить несколько объектов Runnable или Callable для обработки.

ExecutorService executorService = Executors.newFixedThreadPool(10);

Здесь это очень хорошо объяснено. Параллелизм потоков с использованием ExecutorService в Java 8

Попробую это

Ahmad Qureshi 14.02.2019 08:08

Другие вопросы по теме