Tomcat上的Servlet多个请求句柄同时

时间:2018-09-25 08:52:22

标签: java multithreading java-ee tomcat8

我已经编写了一个servlet程序,该程序正在调用java类来生成随机字符串。我还写了一个HTML文件,其中有1000个IFRAME指向Servlet地址。如果有多个请求发送到Servlet,则每个请求将在单独的线程中处理。因此,在这种情况下,将创建1000个线程(1000个请求)。问题是,如果请求数量超过1000,则需要花费大量时间来处理,并且无法处理等等。如果我在后端进行复杂的计算,速度会变慢。为了快速响应,需要在servlet级别(多线程)或tomcat级别(如果可能)进行哪些更改。有什么建议吗?

Servlet代码

@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调用。下面一行已在HTML文件中复制粘贴了1000次。

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

4 个答案:

答案 0 :(得分:0)

尝试在您的UserOperation类中实现java.lang.Runnable接口或扩展java.lang.Thread类以实现多线程。 还可以尝试通过添加具有适当限制的-Xmx参数来增加Java的堆大小。

答案 1 :(得分:0)

您可以在Servlet 3.0中使用异步Servlet;这里有一个例子:

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

仍然存在需要服务器上的端口进行持续连接的问题。发出的请求将占用一个端口,无论它是否占用一个线程,您都可以使用异步servlet减轻事件代码的影响,但是无论如何,端口部分都将保留。缓解端口短缺的唯一方法是将应用程序扩展到多台服务器

答案 2 :(得分:0)

首先,您的servlet很危险,而且不是线程安全的。首先解决。

@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个iframe进行测试,因为您的浏览器通常只能向服务器发送6个并发请求。因此,我实际上怀疑您是否会收到1000个并发请求,但是一次只能从浏览器接收6个请求。 Chrome浏览器甚至可以一次看到它限制为1,因为它看到相同的URL并尝试将结果一乘一地缓存。

简而言之,我怀疑您的servlet速度很慢,但是您的测试方法使它看起来很慢!使用Apache JMeter之类的适当工具将1000个请求发送到您的服务器,然后测试性能。

答案 3 :(得分:0)

尝试在您的UserOperation类中实现java.lang.Runnable接口或扩展java.lang.Thread类以实现多线程。 还可以尝试通过添加具有适当限制的-Xmx参数来增加Java的堆大小。

@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];
       }
   }
}