繁体   English   中英

如何在HttpServlet中处理大数据处理?

[英]How to handle large data processing in HttpServlet?

在我的Java EE应用程序中,有一个servlet来处理大数据过程。 此过程将索引数据库中的所有实体(1300万条记录),并且至少需要15分钟才能完成。 由于服务器处理时间过长,因此客户端抛出了TIMEOUT异常。

@WebServlet("/index")
public class IndexServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    private Logger logger = Logger.getLogger(this.getClass());

    @EJB
    private AddressSession addressSession;

    protected void service(HttpServletRequest request,
            HttpServletResponse response) {

        try {
            addressSession.index();
        } catch (InterruptedException e) {
            logger.error(e);
        }
    }
}

我的问题是如何处理这种情况? 我应该使用异步处理吗?

对于花费很长时间的流程,Web界面应该仅仅是“作业提交”,它可以立即确认请求的接收并将作业排队等待处理。 然后,您可以将此“自然”后端过程与Web层分离。

例如,您不使用http线程池进行后端处理。 有一个单独的执行器来处理提交的作业。 您可以创建执行程序,例如

ExecutorService executorService = Executors.newFixedThreadPool(10);

然后,当有请求进入时,您可以像这样提交作业:

executorService.execute(new Runnable() {
    public void run() {
        // processing
    }
});

现在,如果您还想通过某些Web界面提供有关工作状态的信息,则需要做更多的工作。 您可能想为提交的作业分配一个唯一的ID,并在回执中将其返回。

在这种情况下,由于您正在使用EJB(如果您使用的是EJB 3.1或更高版本),则无需自己对Executor进行编程。 您可以在EJB方法上使用“ 异步”注释来声明性地执行此异步处理。

启用异步支持

正如@ user2494817所说,在这种情况下可以使用异步处理。 要在Servlet上启用异步处理,请在@WebServlet批注上将参数asyncSupported设置为true:

@WebServlet(urlPatterns = {"/index"}, asyncSupported = true)

使用异步上下文

然后,我们需要使用javax.servlet.AsyncContext类,该类提供在服务方法内部执行异步处理所需的功能。 若要获取AsyncContext的实例,请在服务方法的请求对象上调用startAsync()方法。

AsyncContext asyncContext = request.startAsync();

此调用将请求置于异步模式,并确保退出服务方法后不提交响应。 阻塞操作完成后,您必须在异步上下文中生成响应,或者将请求分派到另一个Servlet。

Oracle Java EE 7教程17.12 Servlet中的异步处理中对此进行了描述。 我的解决方案仅考虑一个用户,对于其他用例,我们可能需要更复杂的机制。


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

    private static final long serialVersionUID = 1L;
    private Logger logger = Logger.getLogger(this.getClass());

    @EJB
    private AddressSession addressSession;

    protected void service(HttpServletRequest request,
            HttpServletResponse response) {

        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                try {
                    addressSession.index();
                } catch (InterruptedException e) {
                    logger.error(e);
                }
        }});
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM