首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實現 Comet 長連接技術:Tomcat、Jetty 與 Servlet 3.0 異步處理對比

     編輯:Java 相關知識

Comet 反向 Ajax 技術在 Java 容器中的三種實現範式

Comet(Server-Side Push)讓服務器主動推送數據到瀏覽器,打破 HTTP 請求-響應模型。本文對比 Tomcat 原生 API、Jetty Continuation、Servlet 3.0 標準化異步三種實現路徑。

Comet 三大變體對比

模式機制延遲連接佔用瀏覽器兼容
短輪詢定時 AJAX 請求高 (間隔時間)極短完美
長輪詢請求掛起直到有數據極低中等 (數秒-分)完美
流/iframe持久連接分塊傳輸極低長 (直到超時)僅 Firefox 可靠

Tomcat 實現:CometProcessor 接口

// server.xml 配置 NIO 連接器
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" />

// Servlet 實現
public class WeatherServlet extends HttpServlet implements CometProcessor {
    private MessageSender sender = new MessageSender();
    
    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest req = event.getHttpServletRequest();
        HttpServletResponse resp = event.getHttpServletResponse();
        
        switch (event.getEventType()) {
            case BEGIN:
                req.setAttribute("org.apache.tomcat.comet.timeout", 60_000);
                sender.setConnection(resp);
                new Thread(new DataProducer(sender)).start();
                break;
            case END: case ERROR:
                event.close();
                break;
            case READ:
                throw new UnsupportedOperationException();
        }
    }
}

特點:Tomcat 專有 API,事件模型清晰 (BEGIN/READ/END/ERROR),需配置 NIO 連接器。

Jetty 實現:Continuation 機制

public class WeatherServlet extends HttpServlet {
    private MessageSender sender = new MessageSender();
    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException, ServletException {
        Continuation cont = ContinuationSupport.getContinuation(req);
        if (cont.isPending()) {
            // 恢復階段:發送數據
            resp.getWriter().write((String) cont.getAttribute("data"));
            cont.complete();
        } else {
            // 掛起階段:釋放線程等待數據
            cont.suspend(5_000); // 5秒超時
            new Thread(new DataProducer(cont)).start();
        }
    }
}

特點:Jetty 專有 Continuation API,語義為「掛起-恢復」,線程釋放更直觀。

Servlet 3.0 標準化:AsyncContext

@WebServlet(urlPatterns = "/weather", asyncSupported = true, asyncTimeout = 5000)
public class WeatherServlet extends HttpServlet {
    private MessageSender sender = new MessageSender();
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException, ServletException {
        AsyncContext async = req.startAsync(req, resp);
        sender.setConnection(async); // 傳遞 AsyncContext 而非 Response
        async.start(new DataProducer(sender)); // 容器管理線程池
    }
}

// 發送端
class DataProducer implements Runnable {
    private AsyncContext async;
    public void run() {
        try {
            async.getResponse().getWriter().write("data...");
            async.complete(); // 關鍵:標記完成
        } catch (IOException e) { /* handle */ }
    }
}

優勢:標準化、可移植、容器管理線程池、支援過濾器鏈異步、超時自動處理。

架構選型建議

  • 新項目:強制 Servlet 3.0+ (Tomcat 7+/Jetty 8+),代碼可移植
  • 舊版容器:Tomcat 6 用 CometProcessor,Jetty 6/7 用 Continuation
  • 高併發場景:結合 Netty/Undertow 等非阻塞框架,或升級 Servlet 3.1 非阻塞 IO
  • 生產環境:考慮 WebSocket (JSR 356) 替代 Comet,雙向通訊、更低開銷

客戶端通用代碼 (長輪詢)

function poll() {
    fetch('/weather')
        .then(r => r.text())
        .then(data => {
            document.getElementById('forecast').innerHTML = data;
            poll(); // 立即發起下一輪
        })
        .catch(() => setTimeout(poll, 5000)); // 錯誤重試
}
poll();
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved