Код: Выделить всё
@WebServlet(urlPatterns = { "/test" }, asyncSupported = true)
public class TestServ extends HttpServlet implements AsyncServletTaskProcessor{
public int CALLBACK_TIMEOUT;
public void init() throws ServletException {
// read callback timeout form web.xml as init parameter
CALLBACK_TIMEOUT = Integer.parseInt(getInitParameter("timeout"));
}
@Override
public void doGet(HttpServletRequest rq, HttpServletResponse rs) {
rs.setContentType("text/plain");
rs.setHeader("Access-Control-Allow-Origin", "*");
final AsyncContext asy = rq.startAsync();
// set the timeout
asy.setTimeout(CALLBACK_TIMEOUT);
// attach listener to respond to lifecycle events of this AsyncContext
asy.addListener(new AsyncListenerImpl(asy));
AsyncServletTaskRunner runnable = new AsyncServletTaskRunner ();
asy.start(runnable);
}
}
class AsyncServletTaskRunner implements Runnable {
public void run() {
//outputs: http-nio-8080-exec-n
System.out.println(Thread.getCurrentThread().getName());
//Note1
//callLongProcessingTask();
new Thread() {
public void run() {
//outputs: Thread-n
System.out.println(Thread.getCurrentThread().getName());
//Note2
callLongProcessingTask();
}
}.start();
}
}
Мы вызываем непосредственно вызов start метод AsyncContext (при отладке мы видим: java/org/apache/catalina/core/AsyncContextImpl.java)
Вопрос касается реализации AsyncServletTaskRunner. См. вызов длинного процесса Note1 и Note2. Если мы вызовем задачу длительной обработки в методе run работоспособного интерфейса, см. Примечание 1 (и закомментируем вызов во внутреннем потоке, примечание 2), проблема с нехваткой потока продолжится даже если мы вызываем асинхронные функции сервлета, например, если maxThreadCount tomcat равен 5, после 5.thread начинается блокировка.
Но если мы вызовем задачу длительной обработки в другом потоке как видно в Note2, мы можем обрабатывать 200-300 запросов без каких-либо задержек, и все работает нормально.
Правильно ли мое мнение/диагноз и моя реализация? Поскольку имя потока исполняемого интерфейса (AsyncServletTaskRunner) по-прежнему http-nio, оно потребляет потоки tomcat, и у нас возникают проблемы с потоками, поскольку текущий поток исполняемого интерфейса по-прежнему является потоками обслуживания tomcat, и если он превышает maxThreads tomcat, tomcat может больше не обслуживать запросы.
Кстати, обработка запросов и ответов реализована в Servlet 3.1 NIO с помощью интерфейсов ReadListener и WriteListener, которые не показаны в приведенном выше примере кода. Они зарегистрированы в ServletInputStream и ServletOutputStream. У прослушивателей есть методы обратного вызова, которые вызываются, когда контент доступен для чтения или может быть записан без блокировки контейнера сервлета в потоках ввода-вывода.
Подробнее здесь: https://stackoverflow.com/questions/784 ... management