我们使用具有以下机制的异步 servlet(异步 servlet 不异步运行)
@WebServlet(urlPatterns = { "/test" }, asyncSupported = true)
public class TestServ extends HttpServlet implements AsyncServletTaskProcessor{
/** The exec. */
private ExecutorService exec;
public int CALLBACK_TIMEOUT;
public void init() throws ServletException {
// read callback timeout form web.xml as init parameter
CALLBACK_TIMEOUT = Integer.parseInt(getInitParameter("timeout"));
// read thread pool size form web.xml as init parameter
int size = Integer.parseInt(getInitParameter("threadpoolsize"));
exec = Executors.newFixedThreadPool(size);
}
@Override
public void doGet(HttpServletRequest rq, HttpServletResponse rs) {
rs.setContentType("text/plain");
rs.setHeader("Access-Control-Allow-Origin", "*");
//AsyncContext asy = rq.startAsync(rq, rs);
//asy.start(new Client(asy));
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));
// spawn some task in a background thread
exec.execute(new AsyncServletTaskRunner(asy, this));
}
@Override
public String getServletInfo() {
return "Short description";
}
@Override
public void process(AsyncContext ctx) throws IOException, ServletException {
//do whatever you want to do as process of each thread
}
}
class AsyncServletTaskRunner implements Runnable {
...
}
读取器和写入器是使用 ReadListener 和 WriteListener 以及 ServletOutputStream 编写的。
线程池大小为5。
问题: 我们有 5 个不同的异步 servlet。他们每个人都有自己的执行者。每个都有不同的映射,/test1、/test2 等。但是,如果用户数量增加并且进程时间超过 10 秒,我们就会开始收到 IllegalStateExceptions 并且页面变得无响应。
我们应该为所有 servlet 使用通用的 Executor 吗?泳池的大小怎么样?我们是否应该只为应用程序使用一个异步 servlet,并在实现上进行区分?
另一个问题是我们看到异步servlet的例子没有使用任何Executor,而不是Executor的用法如下,哪种方法更好?
使用执行器:
exec.execute(new AsyncServletTaskRunner(..));
或
asy.start(new AsyncServletTaskRunner(..);
问题:我们有 5 个不同的异步 servlet。他们每个人都有自己的执行者。每个都有不同的映射,/test1、/test2 等。但是,如果用户数量增加并且进程时间超过 10 秒,我们就会开始收到 IllegalStateExceptions 并且页面变得无响应。
这听起来并不奇怪。您正在使用
FixedThreadPoolExecutor
来运行相对长时间运行的任务,因此您可以相对轻松地克服您设置的并发处理能力。
但问题来得更早。 Java EE 应用程序无法随意创建自己的线程,无论它们想要什么。如果您坚持使用执行程序服务,那么您必须使用容器管理的服务。但我不立即明白为什么你需要这样做。 Java EE 容器已经管理多个线程,并且
AsyncContext
有一个用于挂钩的内置机制。
我们应该为所有 servlet 使用通用的 Executor 吗?泳池的大小怎么样?我们是否应该只为应用程序使用一个异步 servlet,并在实现上进行区分?
您可能根本不应该设置自己的执行器服务,但如果您这样做(见上文),那么我看不出为每个 servlet 单独设置一个执行器服务会带来什么好处。
我认为尝试在单个 servlet 上加载所有异步行为没有什么特别的优势。
另一个问题是我们看到了不使用任何 Executor 的异步 Servlet 示例 [...]
是的。
AsyncContext.start()
将指定的任务分配给容器管理的线程。
哪种方法更好?
我想这取决于应用程序,但我建议
AsyncContext.start()
,直到并且除非您发现它在某种程度上不够(以及如何以及为什么)。如果您达到了这一点,那么您将拥有决定自己所需属性所需的所有信息ManagedExecutorService
。