Tomcat怎麼實現非同步Servlet

超人汪小建發表於2017-03-26

有時Servlet在生成響應報文前必須等待某些耗時的操作,比如在等待一個可用的JDBC連線或等待一個遠端Web服務的響應。對於這種情況servlet規範中定義了非同步處理方式,由於Servlet中等待阻塞會導致Web容器整體的處理能力低下,所以對於比較耗時的操作可以放置到另外一個執行緒中進行處理,此過程保留連線的請求和響應物件,在處理完成之後可以把處理的結果通知到客戶端。

下面先看Servlet在同步情況下的處理過程,如圖所示,Tomcat的客戶端請求由管道處理最後會通過Wrapper容器的管道,這時它會調Servlet例項的service方法進行邏輯處理,處理完後響應客戶端,整個處理由Tomcat的Executor執行緒池的執行緒處理,而執行緒池的最大執行緒數使有限制的,所以這個處理過程越短、越快把執行緒讓回執行緒池就越好。但如果Servlet中的處理邏輯耗時越長就會導致長期地佔用Tomcat的處理執行緒池,影響Tomcat的整體處理能力。

Tomcat怎麼實現非同步Servlet
Servlet同步處理

為了解決上面的問題引入了支援非同步的Servlet,同樣是客戶端請求到來,然後通過管道最後進入到Wrapper容器的管道,呼叫Servlet例項的service後,建立一個非同步上下文將耗時的邏輯操作封裝起來,交給使用者自己定義的執行緒池,這時Tomcat的處理執行緒就能馬上回到Executor執行緒池,而不用等待耗時的操作完成才讓出執行緒,從而提升了Tomcat的整體處理能力。這裡要注意的是,由於後面做完耗時的操作後還需要對客戶端響應,所以需要保持住Request和Response物件,以便輸出響應報文到客戶端。

Tomcat怎麼實現非同步Servlet
Servlet非同步處理

再結合一個簡單的非同步程式碼來看Tomcat對Servlet非同步的實現:

public class AsyncServlet extends HttpServlet {

    ScheduledThreadPoolExecutor userExecutor = new ScheduledThreadPoolExecutor(5);

    public void doGet(HttpServletRequest req, HttpServletResponse res) {
        AsyncContext aCtx = req.startAsync(req, res);
        userExecutor.execute(new AsyncHandler(aCtx));
    }

}

public class AsyncHandler implements Runnable {

    private AsyncContext ctx;

    public AsyncHandler(AsyncContext ctx) {
        this.ctx = ctx;
    }

    @Override
    public void run() {
        //耗時操作
        PrintWriter pw;
        try {
            pw = ctx.getResponse().getWriter();
            pw.print("done!");
            pw.flush();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ctx.complete();
    }
}複製程式碼

我們建立一個AsyncServlet,它定義了一個userExecutor執行緒池專門用於處理該Servlet的所有請求的耗時的邏輯操作。這樣就不會佔用Tomcat內部的Executor執行緒池,影響到對其他Servlet的處理。這種思想有點像資源隔離,耗時的操作統一由指定的執行緒池處理,而不要影響其它耗時少的請求處理。

Servlet的非同步的實現就很好理解了,startAsync方法其實就是建立了一個非同步上下文AsyncContext物件,該物件封裝了請求和響應物件。然後建立一個任務用於處理耗時邏輯,後面通過AsyncContext物件獲得響應物件並對客戶端響應,輸出“done!”。完成後要通過complete方法告訴Tomcat內部我已經處理完,Tomcat就會請求物件和響應物件進行回收處理或關閉連線。

歡迎關注:

Tomcat怎麼實現非同步Servlet

相關文章