在 Java 高并發(fā)網(wǎng)絡(luò)編程中,I/O 模型是最核心的基礎(chǔ)之一。
如果你學(xué)習(xí)過 Netty、Redis、Nginx、網(wǎng)關(guān)、RPC 框架,一定會遇到三個概念:
- BIO(Blocking IO)
- NIO(Non-Blocking IO)
- AIO(Asynchronous IO)
很多文章只是簡單介紹概念,但真正面試或者做系統(tǒng)設(shè)計(jì)時(shí),需要理解:
- I/O 架構(gòu)圖
- Reactor 模型
- Linux epoll
- Netty 線程模型
這篇文章會 從架構(gòu) → 底層 → 面試題完整講清楚。
一、三種 I/O 模型對比(超清架構(gòu)圖)
1 BIO 架構(gòu)圖(同步阻塞)
Server
│
┌─────────┼─────────┐
│ │ │
Thread1 Thread2 Thread3
│ │ │
Client1 Client2 Client3
工作方式:
客戶端連接
↓
創(chuàng)建線程
↓
線程阻塞等待數(shù)據(jù)
↓
處理請求
特點(diǎn):
- 一個連接 → 一個線程
- 線程會阻塞等待 IO
問題:
10000 個連接
≈
10000 個線程
會導(dǎo)致:
- 線程上下文切換嚴(yán)重
- 內(nèi)存消耗巨大
- CPU 利用率低
因此 BIO 不適合高并發(fā)系統(tǒng)。
二、NIO 架構(gòu)圖(非阻塞 IO)
NIO 的核心思想:
一個線程管理多個連接
架構(gòu):
┌──────────────┐
Client1 ───────────→ │ │
Client2 ───────────→ │ │
Client3 ───────────→ │ Selector │
Client4 ───────────→ │ │
Client5 ───────────→ │ │
└──────┬───────┘
│
Worker
│
業(yè)務(wù)處理
流程:
客戶端連接
↓
注冊到 Selector
↓
Selector 監(jiān)聽事件
↓
有 IO 事件觸發(fā)
↓
線程處理
NIO 核心組件:
Channel
Buffer
Selector
特點(diǎn):
- 一個線程管理多個連接
- 事件驅(qū)動
- 非阻塞
適合:
高并發(fā)服務(wù)器
聊天系統(tǒng)
網(wǎng)關(guān)系統(tǒng)
三、AIO 架構(gòu)圖(異步 IO)
AIO 的核心思想:
操作系統(tǒng)負(fù)責(zé)完成 IO
完成后通知程序
架構(gòu):
Application
│
發(fā)起 IO 請求
│
▼
Operating System
│
執(zhí)行 IO
│
IO 完成
│
回調(diào)通知
▼
Application Callback
流程:
提交 IO 請求
↓
系統(tǒng)異步執(zhí)行
↓
IO 完成
↓
回調(diào)通知程序
特點(diǎn):
- 真正異步
- 不需要輪詢
- 編程復(fù)雜
但在 Linux 上:
支持不夠成熟
所以實(shí)際使用 遠(yuǎn)少于 NIO。
四、Netty Reactor 模型
Netty 使用的是:
NIO + Reactor
Reactor 是一種 事件驅(qū)動架構(gòu)模型。
核心思想:
監(jiān)聽事件
↓
分發(fā)事件
↓
處理事件
Reactor 架構(gòu)圖
┌──────────────┐
Client Request →│ Reactor │
└──────┬───────┘
│
Event Dispatch
│
┌────────────┴────────────┐
│ │
Handler1 Handler2
│ │
Business Logic Business Logic
作用:
統(tǒng)一監(jiān)聽 IO 事件
統(tǒng)一分發(fā)業(yè)務(wù)處理
五、Netty 完整線程模型圖(主從 Reactor)
Netty 實(shí)際使用:
主從 Reactor 模型
線程結(jié)構(gòu):
┌──────────────┐
Client ───────→ │ BossGroup │
└──────┬───────┘
│
接收連接
│
▼
┌──────────────┐
│ WorkerGroup │
└──────┬───────┘
│
處理讀寫 IO 事件
│
▼
┌──────────────┐
│ Pipeline │
└──────┬───────┘
│
Handler1 → Handler2 → Handler3
│
業(yè)務(wù)處理
執(zhí)行流程:
客戶端連接
↓
Boss 接收連接
↓
分配到 Worker
↓
Worker 處理 IO
↓
Pipeline 執(zhí)行業(yè)務(wù) Handler
優(yōu)勢:
- 線程模型清晰
- 支持高并發(fā)
- 擴(kuò)展性強(qiáng)
六、NIO + epoll 底層原理
NIO 在 Linux 上依賴:
epoll
epoll 是 Linux 的 高性能 IO 多路復(fù)用機(jī)制。
傳統(tǒng) select / poll
早期 IO 模型:
select
poll
問題:
需要遍歷所有連接
假設(shè):
10000 個連接
只有 1 個有數(shù)據(jù)
select 仍然要:
遍歷 10000 次
效率低。
epoll 工作方式
epoll 使用:
事件通知機(jī)制
架構(gòu):
┌────────────┐
Client Conn → │ epoll │
└─────┬──────┘
│
有事件的連接
│
返回
│
程序處理
優(yōu)勢:
只返回有事件的連接
復(fù)雜度:
O(1)
因此:
Redis
Nginx
Netty
Kafka
全部基于 epoll。
七、BIO / NIO / AIO 對比總結(jié)
| 模型 | 類型 | 線程模型 | 并發(fā)能力 |
|---|---|---|---|
| BIO | 同步阻塞 | 一連接一線程 | 低 |
| NIO | 同步非阻塞 | 少量線程 | 高 |
| AIO | 異步非阻塞 | 回調(diào) | 極高 |
一句話總結(jié):
BIO:線程等待 IO
NIO:線程輪詢 IO
AIO:系統(tǒng)完成 IO
八、大廠面試高頻題(10題)
1 BIO、NIO、AIO 的區(qū)別?
核心區(qū)別:
BIO:同步阻塞
NIO:同步非阻塞
AIO:異步非阻塞
2 為什么 NIO 可以支持高并發(fā)?
因?yàn)椋?/p>
一個線程可以管理多個連接
減少:
- 線程創(chuàng)建
- 線程切換
- 內(nèi)存開銷
3 NIO 三大核心組件?
Channel
Buffer
Selector
4 什么是 IO 多路復(fù)用?
IO 多路復(fù)用:
一個線程監(jiān)聽多個 IO
典型實(shí)現(xiàn):
select
poll
epoll
5 epoll 為什么比 select 快?
因?yàn)椋?/p>
epoll 不需要遍歷所有連接
只返回:
有事件的連接
6 Netty 為什么這么快?
原因:
NIO
Reactor 模型
epoll
零拷貝
線程池
7 什么是 Reactor 模型?
Reactor 是一種:
事件驅(qū)動架構(gòu)
核心流程:
事件監(jiān)聽
事件分發(fā)
事件處理
8 Netty 為什么不用 AIO?
原因:
Linux AIO 不成熟
NIO 已經(jīng)足夠快
生態(tài)更穩(wěn)定
9 什么是零拷貝?
零拷貝指:
減少 CPU 數(shù)據(jù)復(fù)制
提升:
網(wǎng)絡(luò) IO 性能
10 Netty 的線程模型是什么?
Netty 使用:
主從 Reactor
結(jié)構(gòu):
BossGroup
WorkerGroup
Pipeline
Handler
九、總結(jié)
Java 網(wǎng)絡(luò) IO 發(fā)展:
BIO → NIO → AIO
但在實(shí)際工程中:
NIO + Reactor + epoll
仍然是 高并發(fā)服務(wù)器的主流架構(gòu)。
所以像:
Netty
Redis
Nginx
Kafka
底層思想幾乎一致。
如果你想深入 Netty / 高并發(fā) / 分布式系統(tǒng),理解這套 IO 模型是非常重要的一步。