Java NIO 只提供非阻塞 API(Selector、Channel、Buffer),Reactor 事件模型需開發者自行封裝或使用 Netty 等成熟框架。
| 模式 | 執行緒架構 | 適用場景 | 複雜度 |
|---|---|---|---|
| 單執行緒 Reactor | 1 個 Selector 執行緒處理 Accept/Read/Write/業務 | 低併發、簡單協議 | 低 |
| 多執行緒 Reactor | 1 個 MainReactor 接受連線,多個 SubReactor 分發 IO,業務線程池處理邏輯 | 高併發、長連線 | 中 |
| Main-Sub Reactor | MainReactor 只負責 Accept,SubReactor 負責 Read/Write,業務再分離 | 極高併發、微服務網關 | 高 |
accept()/read() 會掛起執行緒,NIO 註冊 OP_ACCEPT/OP_READ 後立即返回,執行緒可處理其他 Channel。FileChannel.transferTo()、MappedByteBuffer 可減少用戶/核心態拷貝。public class SimpleReactor implements Runnable {
private final Selector selector;
private final ServerSocketChannel serverSocket;
public SimpleReactor(int port) throws IOException {
selector = Selector.open();
serverSocket = ServerSocketChannel.open();
serverSocket.configureBlocking(false);
serverSocket.bind(new InetSocketAddress(port));
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
}
@Override public void run() {
while (!Thread.interrupted()) {
selector.select(); // 阻塞直到有事件
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if (key.isAcceptable()) accept(key);
else if (key.isReadable()) read(key);
// write 事件同理
}
keys.clear();
}
}
private void accept(SelectionKey key) { /* 接受新連線並註冊 OP_READ */ }
private void read(SelectionKey key) { /* 讀取資料,解碼後丟給業務線程池 */ }
}
EventExecutorGroup 或自定義線程池。selector.selectNow() 忙輪詢、ChannelOutboundBuffer 積壓、GC 停頓。理解 Reactor 原理是調優 Netty、排查網路問題的基石;但落地請站在巨人肩膀上。