大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 Java高階必備之Netty基礎原理

Java高階必備之Netty基礎原理

更新時間:2019-08-04 09:00:00 來源:動力節(jié)點 瀏覽2439次

   


  Netty是Java程序員通向高階之路必須要過的門檻之一。干了幾年的Java程序員發(fā)現業(yè)務開發(fā)似乎就是在SSH的世界里摸滾打爬的時候,會開始感到迷茫,難道程序員的日子就是如此枯燥么?深入使用一下Netty,另一個世界的大門就會開始打開。枯燥的編碼會漸漸變得有趣,自主思考的能力也會開始加強。


  Netty是建立在Java NIO基礎之上最廣泛使用的高性能網絡框架。了解Netty之前,必須對NIO的概念有所了解。


  NIO的意思是非阻塞IO,也就是說單個線程可以同時進行多個IO操作,而不會被任何IO操作阻塞住。同一個線程即能同時Accept網絡套件字,又可以同時對套件字進行讀寫操作,然后還可以同時處理消息。

  NIO基于事件機制,所有的IO操作都能抽象成一個事件。當新連接到來時,可以從內核中拿到ServerSocket的可讀事件。當連接上的消息到來時,可以從內核中拿到Socket的讀事件。當Socket中的緩沖區(qū)未滿的時候,可以從內核中拿到Socket的可寫事件。


  當NIO線程從內核中拿到一個事件Event,就會開始使用相應的事件處理器EventHandler對這個事件進行處理。如果拿到ServerSocket可讀事件,就會調用ServerSocket.accept獲取一個新的Socket連接,然后將這個Socket連接加入到感興趣的描述符列表中,如果拿到Socket可讀事件就會開始調用Socket.read讀取套件字的消息進行處理,處理完畢將返回結果序列化成一個字節(jié)數組,當Socket可以拿到可寫事件時,說明套件字緩沖區(qū)未滿,就拼命的將字節(jié)數組往Socket里灌,也就是調用Socket.write進行IO的寫操作。



  1.png

 

  NIO從內核中拿事件的操作使用的是Selector.select函數調用,它對應操作系統(tǒng)界面的IO多路復用API。在現代操作系統(tǒng)里mac平臺上對應的是kqueue模型,linux平臺對應的是epoll模型,windows平臺對應的是iocp模型。Java是一個跨平臺的語言,JVM底層對操作系統(tǒng)的具體實現進行了抽象,統(tǒng)一向上層提供的是Selector系列API。用戶只需要使用Selector提供的通用API來處理NIO相關功能即可,而無需關系底層具的操作系統(tǒng)API的差別了。


  Selector可以理解為一個描述符對象[SocketChannel]列表,Selector通過調用操作系統(tǒng)API,傳遞一個描述符列表參數,然后就可以拿到內核提供的與所有的描述符相關的事件[Key]列表。

 

2.png 


  上面提到的NIO線程是一個單線程,但是實際上它可以是一個線程池,線程池中的每個線程負責一部分描述符的讀寫操作。它也可以是兩個線程池,一個線程池只用來處理ServerSocket描述符建立新連接,另一個線程池專門干Socket讀寫的事。


 3.png 


  Netty提供了良好的封裝,可以讓我們很方便的配置線程池的功用。代碼中的NioEventLoopGroup代表的就是一個線程池,池中每個線程都是一個獨立的NioEventLoop,即Nio事件循環(huán)。當acceptor線程池接收到一個新連接后會將這個連接通過隊列發(fā)送到讀寫線程池繼續(xù)進行處理。線程池分開的好處是當讀寫線程池繁忙的時候不影響acceptor接收新連接。


  NIO的讀寫操作也是一系列復雜的過程。當NIO讀事件發(fā)生時,線程使用read操作讀取到的消息可能是不完整的,剩下的部分可能還要在接下來多次讀事件發(fā)生后才能讀到完整的一個消息對象字節(jié)數組。也可能read操作讀取到的消息包含多個消息對象,最后剩下的部分又是一個不完整的消息,這就需要在每個描述符關聯(lián)對象中保存中間半包的狀態(tài)。消息和消息之間又有組合關系,比如HTTP POST消息包含HTTP Header和HTTP Body兩個部分,而HTTP Body又可能因為太大而分解為多個HTTP Chunks進行傳輸,這就要求NIO的讀寫消息的設計包含結構層級。寫操作也不是一個簡單的write操作就了事了,寫操作要考慮到內核為每個套件字分配的buffer大小,如果buffer不夠了,write寫進去的數組是不能完全寫進去的,寫不進去的字節(jié)數據必須保留起來,等待下次寫事件發(fā)生時,也就是內核緩沖有空閑空間了,才可以將剩下的數據發(fā)送過去。

 

4.png 


  Netty將消息的讀寫抽象為pipeline消息管道,結構上有點類似于計算機網絡分層結構。pipeline的每一層會對應一個Handler,以上一層輸出的消息結構作為輸入,輸出新的消息結構作為下一層的輸入。pipeline對象掛接在每一個Socket鏈路上。

  

5.png 


  代碼中我們在pipeline里定義了四層Handler,第一個是處理ReadTimeout,當一個連接長達60s沒有任何消息的情況下會向下一層輸出一個讀超時消息。第二層是一個Redis消息解碼器,將Socket中的字節(jié)流轉換成Redis命令對象,第三層是一個Redis消息編碼器,將Redis輸出對象轉稱字節(jié)流,第四層是消息處理器,用來逐個處理Redis命令邏輯,這里一般就是我們復雜的業(yè)務邏輯所在地,我們會在業(yè)務邏輯里最終給Socket回饋消息輸出,這個消息輸出又會走一遍pipeline的每一層,直到轉換成字節(jié)流寫到內核socket緩沖區(qū)中才算完事。


  然后我們設置一些套件字的特殊屬性,比如監(jiān)聽隊列大小、讀寫緩沖警戒水位大小、是否延遲發(fā)送等,然后綁定監(jiān)聽指定端口,服務器就可以開始永無止盡地工作了。



提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 久久香焦| h片在线播放 | 亚洲成人视 | 中文字幕在线不卡精品视频99 | 久久ri精品高清一区二区三区 | 日日骑夜夜骑 | 国产精品国产三级国产普通话 | 99久久精品国产综合一区 | 国产精品视频公开费视频 | 欧美精品专区免费观看 | 天天久久狠狠伊人第一麻豆 | 另类图片色| 亚洲欧美一区二区视频 | 亚洲精品国产成人7777 | 久青草视频97国内免费影视 | 9966久久精品免费看国产 | 天天干天天谢 | 精品煌色视频网站在线观看 | 99ri精品视频在线观看播放 | 国内久久久久影院精品 | 在线观看免费精品国产 | 欧美日韩成人在线观看 | 日韩视频免费在线播放 | 亚洲日本高清 | 国产精品国内免费一区二区三区 | 99网| 久久伊人免费视频 | 国产日本久久久久久久久婷婷 | 99精品国产自产在线观看 | 国产成人精品视频一区二区不卡 | 手机看片福利永久国产日韩 | 亚欧毛片基地国产毛片基地 | 四虎精品免费永久在线 | 久久99精品一久久久久久 | 99麻豆久久久国产精品免费 | 七七七久久久久人综合 | 成人精品免费网站 | 欧美大尺度 边吃奶边做 | 亚洲热热久久九九精品 | 国产日韩精品一区在线观看播放 | www.狠狠操.com |