我一直認爲對於java的學習,掌握基礎的性價比要遠遠高於使用框架,而基礎知識中對於網絡相關知識的掌握也是重中之重。對於一個java程序來講,不管是工做中仍是面試,對於Netty的掌握都是及其重要的。因此博主下定決心深度的學習一下Netty而且作下筆記與心得,供你們一塊兒學習探討。java
Netty的卓越之處在於它是一個高性能、異步事件驅動的NIO框架,目前不少著名的開源框架都使用Netty做爲底層的通訊框架,如Haddop、storm等。linux
好的廢話很少說,咱們直接進入主題。面試
Linux的內核將全部的外部設備都看做一個文件來操做。好比操做一個文件的時候,linux會獲得這個文件的文件描述符(fd),經過這個描述符來操做文件。socket的讀寫儘管不是本地的文件,可是Linux是經過一個相似文件描述符,稱爲socket描述符(socketfd)來操做網絡數據的。描述符就是一個數字,它指向內核中的一個結構體(文件的路徑,數據區等一些屬性)。緩存
這是咱們最最多見的I/O模型,例如咱們日常編寫java程序所用的讀寫文件都是阻塞的。什麼意思呢?就是當程序執行到讀/寫這一步操做的時候不會繼續往下執行代碼,而是等到讀/寫的操做執行完畢。
套接字接口的狀況則是,進程準備接受或發送的數據的時候,,會向內核調用recvfrom()方法,這個方法會一直阻塞,直到數據包接受或發送完畢,或者發生錯誤的時候才返回,在此期間一直等待。網絡
區別於阻塞I/O模型,當咱們接受或發送數據包的時候不會阻塞的等待,而是經過一個循環檢查套接口的狀態,若是緩存區中沒有數據,當進程調用recvfrom()方法的時候,內核直接返回一個EWOULDBLOCK錯誤。當有數據來的時候,才繼續後續操做。框架
這個是Netty底層所使用的 I/O模型,相似於一個小區的物業,管理着全部住戶的快遞,當有快遞小哥來送快遞的時候快遞小哥不用一層一層爬到用戶家中,而是將快遞存放到物業。再由物業來通知用戶取快遞。異步
原理是Linux提供 select/poll方法,經過啓動一個進程來管理全部鏈接的描述符,經過順序掃描全部描述符是否爲就緒狀態。可是這種方式有一個弊端,那就是同時管理的描述符有上限,通常來講最多支持1024個。因此linux在後來提供了pselect/epoll方法,區別於select/poll方法:socket
循環掃描的時候只掃描活躍的文件,所支持的描述符管理上線爲操做系統的最大文件句柄數,好比1GB內存的機器數量大約是10萬個句柄左右,所以如今基本上都是使用的後者。函數
因爲epoll每次都只是掃描活躍的socket,而且在大多數狀況下,只有少部分的socket是活躍的,所以epoll效率會高不少,可是若是在一個高速的LAN環境下,epoll並不會比select/poll的效率高太多;相反相率可能還會稍稍下降。性能
每次接受數據的時候內核須要把數據從內核緩存複製到用戶緩存,這一步內存複製實際上是很下降效率的,epoll是經過內核和用戶空間mmap同一塊內存來實現的。
epoll的API更加簡單。
首先開啓套接口信號驅動,並經過系統調用sigaction執行一個信號處理函數,而後進程繼續工做。當數據準備就緒的時候,就爲該進程生成一個SIGIO信號,經過信號回調通知引用程序來讀取數據。
這種模型與信號驅動模型的主要區別就是:信號驅動I/O模型由內核通知進程能夠開始一個I/O操做了。而異步I/O模型這個逼就更猛了,直接通知進程,勞資已經幫你搞完了。
這五種模型每一種都有很深的學問,博主在這裏只是用我本身所理解的知識來簡單的介紹一下這五種模型,可是若是你對其中的I/O模型有濃厚的興趣,能夠自行對每一種模型進行進一步深度學習。這裏我推薦I/O複用模型,由於Netty的底層就是使用的該模型。