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

Java 網路伺服器程式設計演進:從多執行緒 BIO 到線程池、再到 NIO 反應器模式

     編輯:Java 相關知識

基礎 TCP Echo 伺服器需求

客戶端 TCP 連線後發送資料,伺服器收到立即原樣回傳,連線持續至客戶端關閉。核心挑戰:同時處理多客戶端連線。

階段一:簡單多執行緒模型 (Thread-per-Connection)

public class EchoServer implements Runnable {
    public void run() {
        try (ServerSocket svr = new ServerSocket(7)) {
            while (true) {
                Socket sock = svr.accept();
                new Thread(new EchoSession(sock)).start(); // 每連線建立新執行緒
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}

class EchoSession implements Runnable {
    private final Socket socket;
    EchoSession(Socket s) { this.socket = s; }
    
    public void run() {
        try (InputStream in = socket.getInputStream();
             OutputStream out = socket.getOutputStream()) {
            byte[] buf = new byte[128];
            int count;
            while ((count = in.read(buf)) != -1) {
                out.write(buf, 0, count); // 回顯
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}

優點:邏輯簡單、阻塞式 API 直觀。
缺點:頻繁建立/銷毀執行緒開銷大、執行緒數無上限導致 OOM、上下文切換成本高。

階段二:引入線程池 (Thread Pool)

public class PooledEchoServer implements Runnable {
    public void run() {
        try (ServerSocket svr = new ServerSocket(7)) {
            // 固定大小線程池,這裡用簡易 SyncQueue + Worker 示意
            SyncQueue queue = new SyncQueue<>(100);
            for (int i = 0; i < 50; i++) new Thread(new Worker(queue)).start();
            
            while (true) {
                Socket sock = svr.accept();
                queue.put(new EchoSession(sock)); // 任務入隊,工作者執行緒取出執行
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}

改進:執行緒復用、控制併發上限、EchoSession 實作 Runnable 而非繼承 Thread,解耦任務與執行策略。
局限:固定池大小仍受限於執行緒數,C10K 問題未根治。

階段三:NIO 反應器模式 — 徹底解決 C10K

NIO 核心:非阻塞 I/O + 多路複用 (Selector) + 事件驅動。少量執行緒(通常 1~CPU 核心數)即可處理成萬併發連線。

Reactor 單執行緒架構

// 核心邏輯同前文 NioEchoServer,關鍵點:
// 1. ServerSocketChannel.configureBlocking(false)
// 2. Selector.open() + serverChannel.register(selector, OP_ACCEPT)
// 3. while(select() > 0) { 遍歷 selectedKeys 處理 ACCEPT/READ/WRITE }
// 4. 處理 READ 時解碼完整訊息,編碼回應,必要時註冊 OP_WRITE
// 5. 連線關閉時 channel.close(),取消註冊

Reactor 多執行緒進階(主從/多 Reactor)

  • Main Reactor:專責 OP_ACCEPT,建立連線後分派給 Sub Reactor。
  • Sub Reactor 群組:各自管理一批連線的 OP_READ/WRITE,充分利用多核 CPU。
  • Worker Thread Pool:處理耗時業務邏輯(DB、RPC、計算),避免阻塞 Reactor 執行緒。

這正是 Netty 預設架構(NioEventLoopGroup boss + worker)。

架構選型決策表

併發規模推薦架構典型框架
< 500Thread Pool + BIOTomcat (預設連接器)、Spring Boot 內嵌容器
500 ~ 5,000NIO Reactor (單/多執行緒)Netty、Undertow、Jetty NIO 連接器
> 10,000主從 Reactor + 業務線程池Netty (預設)、gRPC Java、Apache Dubbo

總結

從「一連線一執行緒」到「線程池複用」再到「事件驅動非阻塞」,Java 網路伺服器架構演進本質是資源利用率與擴展性的持續優化。現代微服務、即時通訊、遊戲伺服器幾乎全面採用 Netty 等成熟 NIO 框架,開發者應聚焦業務邏輯,而非重複造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved