Обработка нескольких запросов сервлетов одновременно на tomcat - PullRequest
0 голосов
/ 25 сентября 2018

Я написал программу сервлета, которая вызывает класс java для генерации случайных строк.Я также написал HTML-файл с 1000 IFRAME, указывающим на адрес сервлета.Если к сервлету отправляется несколько запросов, каждый запрос будет обрабатываться в отдельном потоке.Таким образом, в этом случае создается 1000 потоков (1000 запросов).Проблема в том, что обработка занимает много времени и не может обработать, если количество запросов превышает 1000 и так далее.Это становится медленнее, если я делаю сложные вычисления на заднем плане.Какие изменения необходимо сделать на уровне сервлета (многопоточность) или на уровне Tomcat (если это возможно) для быстрого ответа.Любое предложение?

Код сервлета

@WebServlet("/test")
public class MyServlet extends HttpServlet {
            private static final long serialVersionUID = 1L;
private static PrintWriter out=null;
private UserOperation operation=null;
private static int counter=0;
public MyServlet() {
    super();
    operation=new UserOperation();
}
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                            counter++;
                            out=response.getWriter();
                            String output=operation.getResult();
                            System.out.println(counter+":"+output);
                            out.print(output);
                            return;
            }

            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                            doGet(request, response);
            }
}

UserOperation.java

import java.util.Random;

public class UserOperation {
            private Random rand=null;
            private int max=9;
            private int min=0;
            private static final String [] RESULT= {"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE","TEN"};
            public UserOperation() {
                            rand=new Random();
            }
            public String getResult() {
                           int randNum=rand.nextInt((max-min)+1)+min;
                            return RESULT[randNum];
            }
}

HTML-файл

1000 раз вызов IFRAME.ниже строка была скопирована и вставлена ​​1000 раз в файл HTML.

<IFRAME src="http://localhost:8080/MultipleRequest/test" width="30px" height="30px"></IFRAME>

Ответы [ 4 ]

0 голосов
/ 25 сентября 2018

Попробуйте реализовать интерфейс java.lang.Runnable или расширить класс java.lang.Thread в своем классе UserOperation для многопоточности.Также попробуйте увеличить размер кучи Java, добавив параметр -Xmx с допустимым пределом.

@WebServlet(urlPatterns={"/AsyncServlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {

    private static PrintWriter out=null;
    private UserOperation operation=null;
    private static int counter=0;

    public AsyncServlet() {
        super();
        operation=new UserOperation();
    }

   @Override
   public void doGet(HttpServletRequest request,
                     HttpServletResponse response) {
      response.setContentType("text/html;charset=UTF-8");
      final AsyncContext acontext = request.startAsync();
      acontext.start(new Runnable() {
         public void run() {

             counter++;
             try {
                HttpServletResponse response = (HttpServletResponse) acontext.getResponse();

                out=response.getWriter();

                String param = acontext.getRequest().getParameter("param");

                 String output = operation.getResult();
                 System.out.println(counter + ":"+output);
                 out.print(output);

                acontext.complete();

            } catch (IOException e) {
                e.printStackTrace();
            }
         }
      });
   }

   public class UserOperation {
       private Random rand=null;
       private int max=9;
       private int min=0;
       private final String [] RESULT= {"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE","TEN"};
       public UserOperation() {
           rand=new Random();
       }
       public String getResult() {
           int randNum=rand.nextInt((max-min)+1)+min;
           return RESULT[randNum];
       }
   }
}
0 голосов
/ 25 сентября 2018

Вы можете использовать асинхронный сервлет с сервлетом 3.0;Вот пример:

https://www.javaworld.com/article/2077995/java-concurrency/java-concurrency-asynchronous-processing-support-in-servlet-3-0.html

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

0 голосов
/ 25 сентября 2018

Прежде всего, ваш сервлет опасен и не безопасен для потоков.Сначала исправьте это.

@WebServlet("/test")
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private final AtomicInteger counter = new AtomicInteger(0);
    private final UserOperation operation=null;

  public MyServlet() {
    super();
    operation=new UserOperation();
  }
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    int count = this.counter.incrementAndGet();
    PrintWriter out=response.getWriter();
    String output=operation.getResult();
    System.out.println(count + ":" + output);
    out.print(output);
    return;
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
  }
}

Теперь, когда это потокобезопасно, тот факт, что вы думаете, что создано 1000 потоков, неверен.Tomcat имеет пул потоков обработки запросов по умолчанию размером 200. Таким образом, он будет обрабатывать 200 запросов одновременно, а не 1000, как вы думаете.

Кроме того, вам не следует использовать 1000 фреймов для тестирования в качестве браузера.обычно ограничено 6 одновременными запросами к серверу.Поэтому я на самом деле сомневаюсь, что вы получаете 1000 одновременных запросов, но только 6 одновременно из браузера.Chrome может даже ограничить его до 1 за раз, так как он видит один и тот же URL и пытается кэшировать результаты 1 на 1.

Так что я сомневаюсь, что ваш сервлет работает медленно, но ваш метод тестирования делает этокажется медленным!Используйте подходящий инструмент, такой как Apache JMeter , чтобы отправить 1000 запросов на ваш сервер, а затем протестировать производительность.

0 голосов
/ 25 сентября 2018

Попробуйте реализовать интерфейс java.lang.Runnable или расширить класс java.lang.Thread в своем классе UserOperation для многопоточности.Также попробуйте увеличить размер кучи Java, добавив параметр -Xmx с соответствующим пределом.

...