Netty權威指南:I/O 多路複用技術
在I/O程式設計過程中,當需要同時處理多個客戶端接入請求時,可以利用
多執行緒
或者
I/O多路複用技術
進行處理。
I/O多路複用技術透過把多個I/O的阻塞複用到同一個select的阻塞上,從而使得系統在單執行緒的情況下可以同時處理多個客戶端請求。 與傳統的多執行緒/多程式模型比,I/O多路複用的最大優勢是
系統開銷小
,系統不需要建立新的額外程式或者執行緒,也不需要維護這些程式和執行緒的執行,降低了系統的維護工作量,節省了系統資源,I/O 多路複用的主要應用場景如下。
- 伺服器需要同時處理多個處於監聽狀態或者多個連線狀態的套接字;
- 伺服器需要同時處理多種網路協議的套接字。
目前支援I/O多路複用的系統呼叫有
select
、
pselect
、
poll
、
epoll
,在Linux網路程式設計過程中,很長一段時間都使用
select
做輪詢和網路事件通知,然而
select
的一些固有缺陷導致了它的應用受到了很大的限制,最終Linux不得不在新的核心版本中尋找
select
的替代方案,最終選擇了
epoll
。
epoll
與
select
的原理比較類似,為了克服
select
的缺點,
epoll
作了很多重大改進,現總結如下。
1.支援一一個程式開啟的socket描述符( FD)不受限制(僅受限於作業系統的最大檔案控制程式碼數)。
select最大的缺陷就是單個程式所開啟的FD是有一定限制的,它由
FD_ SETSIZE
設定,預設值是1024。 對於那些需要支援上萬個TCP連線的大型伺服器來說顯然太少了。可以選擇修改這個宏然後重新編譯核心,不過這會帶來網路效率的下降。我們也可以透過選擇多程式的方案(傳統的Apache方案)解決這個問題,不過雖然在Linux上建立程式的代價比較小,但仍舊是不可忽視的。另外,程式間的資料交換非常麻煩,對於Java 來說,由於沒有共享記憶體,需要透過
Socket通訊
或者其他方式進行資料同步,這帶來了額外的效能損耗,增加了程式複雜度,所以也不是一種完美的解決方案。值得慶幸的是,
epoll
並沒有這個限制,它所支援的
FD
上限是作業系統的最大檔案控制程式碼數,這個數字遠遠大於 1024。例如,在1GB記憶體的機器,上大約是10萬個控制程式碼左右,具體的值可以透過
cat./proc/sys/fs/file-max
察看,通常情況下這個值跟系統的記憶體關係比較大。
2.I/O效率不會隨著FD數目的增加而線性下降。
傳統
select/poll
的另一個致命弱點,就是當你擁有一個很大的
socket
集合時,由於網路延時或者鏈路空閒,任一時刻只有少部分的
socket
是“活躍”的,但是
select/poll
每次呼叫都會線性掃描全部的集合,導致
效率呈現線性下降。
epoll
不存在這個問題,它只會對“活躍”的
socket
進行操作一這是因為在核心實現中,
epoll
是根據每個fd上面的
callback
函式實現的。那麼,只有“活躍”的
socket
才會去主動呼叫
callback
函式,其他idle 狀態的
socket
則不會。在這點上,
epoll
實現了一個偽AIO。針對
epoll
和
select
效能對比的
benchmark
測試表明:如果所有的
socket
都處於活躍態一例如一一個高速LAN環境,
epoll
並不比
select/poll
效率高太多;相反,如果過多使用
epoll_ctl
,效率相比還有稍微地降低。但是一旦使用
idleconnections
模擬WAN環境,epoll的效率就遠在
select/poll
之上了。
3.使用mmap加速核心與使用者空間的訊息傳遞。
無論是
select
、
poll
還是
epoll
都需要核心把FD訊息通知給使用者空間,如何避免不必要的記憶體複製就顯得非常重要,
epoll
是透過核心和使用者空間
mmap
同一塊記憶體來實現的。
4.epoll 的API更加簡單。
包括建立一個
epoll描述符
、
新增監聽事件
、
阻塞等待所監聽的事件發生
、
關閉epoll描述符
等。
值得說明的是,用來克服
select/poll
缺點的方法不只有epoll, epoll 只是一種Linux的實現方案。在freeBSD
下有kqueue
,而dev/poll
是最古老的Solaris的方案,使用難度依次遞增。kqueue 是freebsd的寵兒,它實際上是一個功能相當豐富的kernel事件佇列,它不僅僅是select/poll
的升級,而且可以處理signal、目錄結構變化、程式等多種事件。kqueue是邊緣觸發的。/dev/poll
是Solaris的產物,是這一系列高效能API中最早出現的。Kernel提供了一個特殊的裝置檔案/dev/poll
,應用程式開啟這個檔案得到操作fd_ set
的控制程式碼,透過寫入pollfd
來修改它,一個特殊的ioctl
呼叫用來替換select。不過由於出現的年代比較早,所以/dev/poll
的介面實現比較原始。
從BIO到NIO是Java通訊類庫邁出的一小步,但卻對Java在高效能通訊領域的發展起到了關鍵性的推動作用。
隨著基於NIO的各類NIO框架的發展,以及基於NIO的Web伺服器的發展,Java在很多領域取代了C和C++,成為企業服務端應用開發的首選語言。
喜歡這篇文章的朋友們可以關注個人簡介中的公眾號
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69964492/viewspace-2766572/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- I/O多路複用技術(multiplexing)
- Netty權威指南:Java的I/O演進NettyJava
- 一文搞懂I/O多路複用及其技術
- Netty權威指南:Linux網路 I/O 模型簡介NettyLinux模型
- 從網路I/O模型到Netty,先深入瞭解下I/O多路複用模型Netty
- 【Linux網路程式設計】I/O 多路複用技術Linux程式設計
- 多路I/O複用:select、poll、epoll(二)
- LinuxI/O多路複用Linux
- 詳解Go語言I/O多路複用netpoller模型Go模型
- IO多路複用技術總結
- 【面試】I/O 複用面試
- 一篇文章幫你徹底搞清楚“I/O多路複用”和“非同步I/O”的前世今生非同步
- Go netpoll I/O 多路複用構建原生網路模型之原始碼深度解析Go模型原始碼
- Linux下的5種I/O模型與3組I/O複用Linux模型
- 網路程式設計-I/O複用程式設計
- 多路複用
- 理解IO多路複用
- JavaScript 日期權威指南JavaScript
- netty系列之:手持framecodec神器,建立多路複用http2客戶端NettyHTTP客戶端
- netty系列之:效能為王!建立多路複用http2伺服器NettyHTTP伺服器
- IO多路複用詳解
- IO多路複用小故事
- Redis 和 IO 多路複用Redis
- Java 13權威指南 - CodeFXJava
- JavaScript權威指南(6)——物件JavaScript物件
- [譯] JAVASCRIPT 日期權威指南JavaScript
- 計算機網路——多路複用與多路分解計算機網路
- Linux I/O 原理和 Zero-copy 技術全面揭祕Linux
- 玩轉 PHP 網路程式設計全套之 I/O 複用PHP程式設計
- [Java併發]IO多路複用Java
- 徹底搞懂IO多路複用
- IO多路複用原理&場景
- BIO、NIO、多路複用IO、AIOAI
- JavaScript權威指南(8)——函式JavaScript函式
- JavaScript權威指南(7)——陣列JavaScript陣列
- Elasticsearch 權威指南(中文版)Elasticsearch
- javascript權威指南——函式篇JavaScript函式
- HBase權威指南【中文版】