通道Channel-IO 多路复用
我們試想一下這樣的現實場景:
一個餐廳同時有100 位客人到店,當然到店后第一件要做的事情就是點菜。但是問題來了,餐廳老板為了節約人力成本目前只有一位大堂服務員拿著唯一的一本菜單等待客人進行服務。
那么最笨(但是最簡單)的方法是(方法A),無論有多少客人等待點餐,服務員都把僅有的一份菜單遞給其中一位客人,然后站在客人身旁等待這個客人完成點菜過程。在記錄客人點菜內容后,把點菜記錄交給后堂廚師。然后是第二位客人。。。。然后是第三位客人。很明顯,只有腦袋被門夾過的老板,才會這樣設置服務流程。因為隨后的80 位客人,再等待超時后就會離店(還會給差評)。
于是還有一種辦法(方法B),老板馬上新雇傭99 名服務員,同時印制99 本新的菜單。每一名服務員手持一本菜單負責一位客人(關鍵不只在于服務員,還在于菜單。因為沒有菜單客人也無法點菜)。在客人點完菜后,記錄點菜內容交給后堂廚師(當然為了更高效,后堂廚師最好也有100 名)。這樣每一位客人享受的就是VIP 服務咯,當然客人不會走,但是人力成本可是一個大頭哦(虧死你)。
另外一種辦法(方法C),就是改進點菜的方式,當客人到店后,自己申請一本菜單。想好自己要點的才后,就呼叫服務員。服務員站在自己身邊后記錄客人的菜單內容。將菜單遞給廚師的過程也要進行改進,并不是每一份菜單記錄好以后,都要交給后堂廚師。服務員可以記錄號多份菜單后,同時交給廚師就行了。那么這種方式,對于老板來說人力成本是最低的;對于客人來說,雖然不再享受VIP 服務并且要進行一定的等待,但是這些都是可接受的;對于服務員來說,基本上她的時間都沒有浪費,基本上被老板壓桿了最后一滴油水。
如果您是老板,您會采用哪種方式呢?
到店情況:并發量。到店情況不理想時,一個服務員一本菜單,當然是足夠了。所以不同的老板在不同的場合下,將會靈活選擇服務員和菜單的配置。
客人:客戶端請求
點餐內容:客戶端發送的實際數據
老板:操作系統
人力成本:系統資源
菜單:文件狀態描述符(FD)。操作系統對于一個進程能夠同時持有的文件狀態描述符的個數是有限制的,在linux系統中$ulimit -n 查看這個限制值,當然也是可以(并且應該)進行內核參數調整的。
服務員:操作系統內核用于IO 操作的線程(內核線程)
廚師:應用程序線程(當然廚房就是應用程序進程咯)
方法A:同步IO
方法B:同步IO
方法C:多路復用IO
目前流行的多路復用IO 實現主要包括四種:select、poll、epoll、kqueue。下表是他們的一些重要特性的比較:
| IO模型 | 相對性能 | 關鍵思路 | 操作系統 | JAVA支持 |
| select | 較高 | Reactor | windows/Linux | 支持,Reactor 模式(反應器設計模式)。Linux 操作 系統的kernels 2.4 內核版本之前, 默認使用 select;而目前windows 下對同步IO 的支持,都 是select 模型。 |
| poll | 較高 | Reactor | Linux | Linux 下的JAVA NIO 框架,Linux kernels 2.6 內 核版本之前使用poll 進行支持。也是使用的 Reactor 模式。 |
| epoll | 高 | Reactor/Proactor | Linux | Linux kernels 2.6 內核版本及以后使用epoll 進行 支持;Linux kernels 2.6 內核版本之前使用poll 進行支持;另外一定注意,由于Linux 下沒有 Windows 下的IOCP 技術提供真正的異步IO 支 持,所以Linux 下使用epoll 模擬異步IO。 |
| kqueue | 高 | Proactor | Linux | 目前JAVA 的版本不支持。 |
多路復用IO 技術最適用的是“高并發”場景,所謂高并發是指1 毫秒內至少同時有上千個連接請求準備好。其他情況下多路復用IO 技術發揮不出來它的優勢。另一方面,使用JAVA NIO 進行功能實現,相對于傳統的Socket 套接字實現要復雜一些,所以實際應用中,需要根據自己的業務需求進行技術選擇。
?
總結
以上是生活随笔為你收集整理的通道Channel-IO 多路复用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通道Channel-使用NIO 写入数据
- 下一篇: NIO 源码初探