1. 同步阻塞BIO
-
serversocket
負責綁定IP和Port胎署,socket
負責發(fā)起連接操作。連接成功后诱担,通過輸入/輸出流進行同步阻塞式通信毡证。 - 傳統(tǒng)請求-應答模型,Acceptor線程每接受一個請求蔫仙,創(chuàng)建一個線程處理請求并返回料睛。
2. 偽異步IO
- 后來考慮到高性能/高并發(fā)場景,演進了用線程池/消息隊列實現(xiàn)1個或多個線程處理N個客戶端摇邦。但底層通信機制仍是同步阻塞IO恤煞,故稱作“偽異步”。線程池中的線程數(shù)量和隊列大小可控施籍,因此不會導致資源耗盡和宕機居扒。
- 弊端:JDK的API文檔中,對于InputStream和OutputStream中的read(byte[] b)和write(byte[] b)操作丑慎,都是同步阻塞的喜喂,亦即一直阻塞直到發(fā)生如下事件:
- 有數(shù)據(jù)可讀。
- 讀到數(shù)據(jù)末尾竿裂。
- 發(fā)生空指針或IO異常玉吁。
如果大量連接上來,前端只有一個Acceptor線程接入請求腻异,那么进副,之前的請求在線程池中的隊列(阻塞隊列實現(xiàn))中排隊,隊列滿悔常,入隊操作阻塞影斑,新請求將被拒絕。破解這一難題这嚣,NIO入場鸥昏。
3. NIO編程
官方
New IO
,更多人接受Non-block IO
.與Socket和ServerSocket類似,NIO提供了SocketChannel和ServerSocketChannel套接字通道實現(xiàn)姐帚,且支持阻塞和非阻塞模式吏垮。
3.1. 緩沖區(qū)Buffer
在NIO中,所有的數(shù)據(jù)操作都是面對緩沖區(qū)的,從緩沖區(qū)讀膳汪,往緩沖區(qū)寫唯蝶。實現(xiàn)原理是數(shù)組。
3.2. 通道Channel
通道與流的不同遗嗽,在于通道是雙向的粘我,而流是單向的。通道可用于讀痹换、寫征字、同時讀寫。同時支持阻塞和非阻塞模式娇豫。
3.3. 多路復用器Selector
多路選擇器提供了選擇已經(jīng)就緒的任務的能力匙姜。Selector會不斷輪詢注冊其上的Channel,如果某個Channel上有新的TCP連接冯痢、讀氮昧、寫事件,這個Channel就處于就緒狀態(tài)浦楣,會被Selector輪詢出來袖肥。JDK使用了epoll()代替了select()實現(xiàn),沒有最大連接句柄數(shù)1024/2048的限制振劳,一般1GB內存支持100 000個連接椎组。
4. AIO 編程
NIO2.0引入新的異步通道的概念,并提供了異步文件通道和異步套接字通道的實現(xiàn)澎迎。是真正的異步非阻塞IO庐杨,對應unix的事件驅動IO(AIO),不需要Selector對其輪詢即可實現(xiàn)異步讀寫夹供。
5. 總結
5.1. 不選擇原生NIO編程原因
- NIO類庫和API非常負責灵份,使用麻煩。
- 需具備其他技能做鋪墊哮洽,如Java多線程編程填渠,Reactor模式等。
- 可靠性不夠鸟辅,如客戶端斷連重連氛什,網(wǎng)絡閃斷,半包讀寫匪凉,失敗緩存等枪眉。
- JDK的NIO bug,如epoll bug再层,它會導致Selector空輪詢贸铜,導致CPU使用率100%堡纬。
5.2. 為什么選擇Netty
- API使用簡單,開發(fā)門檻低蒿秦。
- 功能強大烤镐,預置了多種編解碼功能,支持主流協(xié)議棍鳖。
- 定制能力強炮叶。
- 性能高。
- 成熟穩(wěn)定渡处,修復了已發(fā)現(xiàn)的所有NIO bug镜悉。
- 社區(qū)活躍,版本迭代周期短骂蓖。
- 經(jīng)過了大規(guī)模的商用考驗积瞒。