簡體   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