简体   繁体   中英

How to handle large data processing in HttpServlet?

In my Java EE application, there's a servlet to handle a large data process. This process indexes all entities in the database (13 millions records) and it need at least 15 minutes to complete. Since the server takes too long time on processing, an TIMEOUT exception was thrown by the client.

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

My question is how to handle this situation ? Should I use asynchronous processing ?

For processes that take so long the web interface should be just a "job submission" that immediately acknowledges the receipt of the request and queues the job for processing. Then you decouple this "by nature" back end process from your web layer.

For example, you don't use the http thread pool to do the back end processing. Have a separate Executor for processing the submitted job. You can create the executor for example with

ExecutorService executorService = Executors.newFixedThreadPool(10);

Then when a request comes in, you submit the job like so:

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

Now if you also want to provide information about the status of your job through some web interface you need to do some more work. You might want to assign a unique id to the submitted job and return it with the acknowledgement of the receipt.

In this case since you are using EJBs (if you're on EJB 3.1 or higher) you don't need to program the Executor by yourself. You can use the Asynchronous annotation on your EJB method to do this asynchronous processing declaratively.

Enable asynchronous support

As @user2494817 said, asynchronous processing can be used in this situation. To enable asynchronous processing on a servlet, set the parameter asyncSupported to true on the @WebServlet annotation :

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

Use asynchronous context

Then we need to use the javax.servlet.AsyncContext class, which provides the functionality that we need to perform asynchronous processing inside service methods. To obtain an instance of AsyncContext, call the startAsync() method on the request object of the service method.

AsyncContext asyncContext = request.startAsync();

This call puts the request into asynchronous mode and ensures that the response is not committed after exiting the service method. You have to generated the response in the asynchronous context after the blocking operation completes or dispatch the request to another servlet.

This is described in Oracle Java EE 7 Tutorial - 17.12 Asynchronous Processing in Servlets . My solution considers only one user, for other use-cases, we might need more complex mechanism.


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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