Netty相關知識彙總

一、TCP、UDP的區別?html

TCP與UDP區別總結:java

1)、TCP面向鏈接(如打電話要先撥號創建鏈接);UDP是無鏈接的,即發送數據以前不須要創建鏈接。react

2)、TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付web

3)、TCP面向字節流,其實是TCP把數據當作一連串無結構的字節流;UDP是面向報文的 UDP沒有擁塞控制,所以網絡出現擁塞不會使源主機的發送速率下降(對實時應用頗有用,如IP電話,實時視頻會議等)算法

4)、每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊數據庫

5)、TCP首部開銷20字節;UDP的首部開銷小,只有8個字節編程

6)、TCP的邏輯通訊信道是全雙工的可靠信道,UDP則是不可靠信道後端

二、TCP協議如何保證可靠傳輸?數組

www.cnblogs.com/xiaokang01/…安全

三、TCP的握手、揮手機制?

TCP的握手機制:

TCP的揮手機制:

詳情參考文章: blog.csdn.net/qzcsu/artic…

四、TCP的粘包/拆包緣由及其解決方法是什麼?

爲何會發生TCP粘包、拆包? 發生TCP粘包、拆包主要是因爲下面一些緣由:

1).應用程序寫入的數據大於套接字緩衝區大小,這將會發生拆包。

2).應用程序寫入數據小於套接字緩衝區大小,網卡將應用屢次寫入的數據發送到網絡上,這將會發生粘包。

3).進行MSS(最大報文長度)大小的TCP分段,當TCP報文長度-TCP頭部長度>MSS的時候將發生拆包。

4).接收方法不及時讀取套接字緩衝區數據,這將發生粘包。

粘包、拆包解決辦法:

TCP自己是面向流的,做爲網絡服務器,如何從這源源不斷涌來的數據流中拆分出或者合併出有意義的信息呢?一般會有如下一些經常使用的方法:

1)、發送端給每一個數據包添加包首部,首部中應該至少包含數據包的長度,這樣接收端在接收到數據後,經過讀取包首部的長度字段,便知道每個數據包的實際長度了。

2)、發送端將每一個數據包封裝爲固定長度(不夠的能夠經過補0填充),這樣接收端每次從接收緩衝區中讀取固定長度的數據就天然而然的把每一個數據包拆分開來。

3)、能夠在數據包之間設置邊界,如添加特殊符號,這樣,接收端經過這個邊界就能夠將不一樣的數據包拆分開。

詳情參考文章:www.cnblogs.com/panchanggui…

五、Netty的粘包/拆包是怎麼處理的,有哪些實現?

對於粘包和拆包問題,常見的解決方案有四種:

1)、客戶端在發送數據包的時候,每一個包都固定長度,好比1024個字節大小,若是客戶端發送的數據長度不足1024個字節,則經過補充空格的方式補全到指定長度;Netty提供的FixedLengthFrameDecoder

2)、客戶端在每一個包的末尾使用固定的分隔符,例如\r\n,若是一個包被拆分了,則等待下一個包發送過來以後找到其中的\r\n,而後對其拆分後的頭部部分與前一個包的剩餘部分進行合併,這樣就獲得了一個完整的包;Netty提供LineBasedFrameDecoder與DelimiterBasedFrameDecoder

3)、將消息分爲頭部和消息體,在頭部中保存有當前整個消息的長度,只有在讀取到足夠長度的消息以後纔算是讀到了一個完整的消息;Netyy提供了LengthFieldBasedFrameDecoder與LengthFieldPrepender

4)、經過自定義協議進行粘包和拆包的處理。Netty提供了經過實現MessageToByteEncoder和ByteToMessageDecoder來實現

更詳細請閱讀文章:www.cnblogs.com/AIPAOJIAO/p…

六、同步與異步、阻塞與非阻塞的區別?

簡單點理解就是:

1). 同步,就是我調用一個功能,該功能沒有結束前,我死等結果。

2). 異步,就是我調用一個功能,不須要知道該功能結果,該功能有結果後通知我(回調通知)

3). 阻塞,就是調用我(函數),我(函數)沒有接收完數據或者沒有獲得結果以前,我不會返回。

4). 非阻塞,就是調用我(函數),我(函數)當即返回,經過select通知調用者

同步IO和異步IO的區別就在於:數據拷貝的時候進程是否阻塞

阻塞IO和非阻塞IO的區別就在於:應用程序的調用是否當即返回

七、說說網絡IO模型?

八、BIO、NIO、AIO分別是什麼?

BIO:同步並阻塞,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。BIO方式適用於鏈接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4之前的惟一選擇,但程序直觀簡單易理解。

NIO:同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持。

AIO:異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理.AIO方式使用於鏈接數目多且鏈接比較長(重操做)的架構,好比相冊服務器,充分調用OS參與併發操做,編程比較複雜,JDK7開始支持。

九、select、poll、epoll的機制及其區別?

1).單個進程打開的文件描述符(fd文件句柄)不一致

select :有最大鏈接數限制數爲1024,單個進程所能打開的最大鏈接數由FD_ZETSIZE宏定義。

poll:poll本質上與select沒有區別,可是它沒有最大鏈接數的限制,緣由是它是基於鏈表來存儲的。

epoll:雖然鏈接有上限,可是很大,1G內存的機器能夠打開10萬左右的鏈接,以此類推。

2).監聽Socket的方式不一致

select :輪詢的方式,一個一個的socket檢查過去,發現有socket活躍時才進行處理,當線性socket增多時,輪詢的速度將會變得很慢,形成線性形成性能降低問題。

poll:對select稍微進行了優化,只是修改了文件描述符,可是監聽socket的方式仍是輪詢。

expoll:epoll內核中實現是根據每一個fd上的callback函數來實現的,只有活躍的socket纔會主動調用callback,通知expoll來處理這個socket。(會將鏈接的socket註冊到epoll中, 至關於socket的花名冊, 若是有一個socket活躍了, 會回調一個函數, 通知epoll,趕忙過來處理)

3).內存空間拷貝方式(消息傳遞方式)不一致

select:內核想將消息傳遞到用戶態,須要將數據從內核態拷貝到用戶態,這個過程很是的耗時

poll:同上

epoll:epoll的內核和用戶空間共享一塊內存,所以內存態數據和用戶態數據是共享的

select、poll、epoll時間複雜度分別是:O(n)、O(n)、O(1)

十、說說你對Netty的瞭解?

這個沒用過的話,就不要死撐了。用過的估計不用找了吧。

十一、Netty跟Java NIO有什麼不一樣,爲何不直接使用JDK NIO類庫?

說說NIO有什麼缺點吧:

NIO的類庫和API仍是有點複雜,好比Buffer的使用 Selector編寫複雜,若是對某個事件註冊後,業務代碼過於耦合 須要瞭解不少多線程的知識,熟悉網絡編程 面對斷連重連、保丟失、粘包等,處理複雜 NIO存在BUG,根據網上言論說是selector空輪訓致使CPU飆升,具體有興趣的能夠看看JDK的官網

Netty主要的優勢有:

框架設計優雅,底層模型隨意切換適應不一樣的網絡協議要求

提供不少標準的協議、安全、編碼解碼的支持

解決了不少NIO不易用的問題

社區更爲活躍,在不少開源框架中使用,如Dubbo、RocketMQ、Spark等

底層核心有:Zero-Copy-Capable Buffer,很是易用的靈拷貝Buffer(這個內容頗有意思,稍後專門來講);統一的API;標準可擴展的時間模型

傳輸方面的支持有:管道通訊(具體不知道幹啥的,還請老司機指教);Http隧道;TCP與UDP

協議方面的支持有:基於原始文本和二進制的協議;解壓縮;大文件傳輸;流媒體傳輸;protobuf編解碼;安全認證;http和websocket

總之提供了不少現成的功能能夠直接供開發者使用。

十二、Netty組件有哪些,分別有什麼關聯?

Channel ----Socket

EventLoop ----控制流,多線程處理,併發;

ChannelHandler和ChannelPipeline

Bootstrap 和 ServerBootstrap

更多詳情能夠閱讀:blog.csdn.net/summerZBH12…

1三、說說Netty的執行流程?

1)、建立ServerBootStrap實例

2)、設置並綁定Reactor線程池:EventLoopGroup,EventLoop就是處理全部註冊到本線程的Selector上面的Channel

3)、設置並綁定服務端的channel

4)、5)、建立處理網絡事件的ChannelPipeline和handler,網絡時間以流的形式在其中流轉,handler完成多數的功能定製:好比編解碼 SSl安全認證

6)、綁定並啓動監聽端口

7)、當輪訓到準備就緒的channel後,由Reactor線程:NioEventLoop執行pipline中的方法,最終調度並執行channelHandler

更多請參考文章:juejin.im/post/5bf8fb…

1四、Netty高性能體如今哪些方面?

www.infoq.cn/article/net…

1五、Netty的線程模型是怎麼樣的?

Reactor線程模型

Reactor單線程模型 一個NIO線程+一個accept線程:

Reactor多線程模型

Reactor主從模型 主從Reactor多線程:多個acceptor的NIO線程池用於接受客戶端的鏈接

Netty能夠基於如上三種模型進行靈活的配置。

總結

Netty是創建在NIO基礎之上,Netty在NIO之上又提供了更高層次的抽象。在Netty裏面,Accept鏈接可使用單獨的線程池去處理,讀寫操做又是另外的線程池來處理。Accept鏈接和讀寫操做也可使用同一個線程池來進行處理。而請求處理邏輯既可使用單獨的線程池進行處理,也能夠跟放在讀寫線程一塊處理。線程池中的每個線程都是NIO線程。用戶能夠根據實際狀況進行組裝,構造出知足系統需求的高性能併發模型。

1六、Netty的零拷貝提體如今哪裏,與操做系統上的有什麼區別?

傳統意義的拷貝是在發送數據的時候, 傳統的實現方式是:

  1. File.read(bytes)
  2. Socket.send(bytes)

這種方式須要四次數據拷貝和四次上下文切換:

  1. 數據從磁盤讀取到內核的read buffer
  2. 數據從內核緩衝區拷貝到用戶緩衝區
  3. 數據從用戶緩衝區拷貝到內核的socket buffer
  4. 數據從內核的socket buffer拷貝到網卡接口(硬件)的緩衝區

零拷貝的概念明顯上面的第二步和第三步是沒有必要的,經過java的FileChannel.transferTo方法,能夠避免上面兩次多餘的拷貝(固然這須要底層操做系統支持)

  1. 調用transferTo,數據從文件由DMA引擎拷貝到內核read buffer
  2. 接着DMA從內核read buffer將數據拷貝到網卡接口buffer上面的兩次操做都不須要CPU參與,因此就達到了零拷貝。

Netty中的零拷貝主要體如今三個方面:

一、bytebufferNetty發送和接收消息主要使用bytebuffer,bytebuffer使用對外內存(DirectMemory)直接進行Socket讀寫。緣由:若是使用傳統的堆內存進行Socket讀寫,JVM會將堆內存buffer拷貝一份到直接內存中而後再寫入socket,多了一次緩衝區的內存拷貝。DirectMemory中能夠直接經過DMA發送到網卡接口

二、Composite Buffers傳統的ByteBuffer,若是須要將兩個ByteBuffer中的數據組合到一塊兒,咱們須要首先建立一個size=size1+size2大小的新的數組,而後將兩個數組中的數據拷貝到新的數組中。可是使用Netty提供的組合ByteBuf,就能夠避免這樣的操做,由於CompositeByteBuf並無真正將多個Buffer組合起來,而是保存了它們的引用,從而避免了數據的拷貝,實現了零拷貝。

三、對於FileChannel.transferTo的使用Netty中使用了FileChannel的transferTo方法,該方法依賴於操做系統實現零拷貝。

1七、Netty的內存池是怎麼實現的?

netty內存池實現原理

netty內存池能夠分配堆內存和非堆內存(Direct內存),內存分配的核心算法是相似的,從堆內存分配代碼入手來學習整個內存池的原理。netty框架處理IO事件時,使用ByteBuf承載數據。ByteBuf的內存分配由PooledByteBufAllocator來執行,最終的內存分配工做會被委託給PoolArena,堆內存分配的PoolArena實現是HeapArena。

netty一般被用於高併發系統,多線程競爭加鎖會影響內存分配的效率,爲了緩解高併發時的線程競爭,netty容許使用者建立多個分配器(PoolArena)來分離線程競爭,提升內存分配效率。可經過PooledByteBufAllocator構造子中的nHeapArena參數來設置PoolArena的數量,或者直接取框架中的默認值,經過如下代碼決定默認值,默認值根據CPU核心數、JVM最大可用內存以及默認內存塊(PoolChunk)大小等參數來計算這個默認值,計算邏輯是:

1)獲取系統變量io.netty.allocator.numHeapArenas,經過System.setProperty("io.netty.allocator.numHeapArenas",xxx)或者增長JVM啓動參數-Dio.netty.allocator.numHeapArenas=xxx設置,若是設置了值,把這個值當作Arena的個數。

2)若是沒有設置io.netty.allocator.numHeapArenas系統變量,計算CPU核心數*2和JVM最大可用內存/默認內存塊大小/2/3,取其中一個較少的值當作PoolArena的個數。

肯定PoolArena個數以後框架會建立一個PoolArena數組,數組中全部的PoolArena都會用來執行內存分配。線程申請內存分配時,線程會在這個PoolArena數組中挑選一個當前被佔用次數最少的Arena執行內存分配。

此外,netty使用擴展的線程對象FastThreadLocalThread來優化ThreadLocal性能,具體的優化思路是:默認的ThreadLocal使用ThreadLocalMap存儲線程局部變量,它的實現方式相似於HashMap,須要計算hashCode定位到線程局部變量所在Entry的索引,而FastThreadLocalThread使用FastThreadLocal代替ThreadLocal,FastThreadLocalThread用一個數組來維護線程變量,每一個FastThreadLocal維護一個index,該index就是線程局部變量在數組中的位置,線程變量直接經過index訪問無需計算hashCode,FastThreadLocal的優點是減小了hashCode的計算過程,雖然性能只會有輕微的提高,但在高併發系統中,即便只是輕微的提高也會成倍放大。

更多請閱讀文章:baijiahao.baidu.com/s?id=164049…

1八、Netty的對象池是怎麼實現的?

Netty 並無使用第三方庫實現對象池,而是本身實現了一個相對輕量的對象池。經過使用 threadLocal,避免了多線程下取數據時可能出現的線程安全問題,同時,爲了實現多線程回收同一個實例,讓每一個線程對應一個隊列,隊列連接在 Stack 對象上造成鏈表,這樣,就解決了多線程回收時的安全問題。同時,使用了軟引用的map 和 軟引用的 thradl 也避免了內存泄漏。

更詳細的可閱讀文章:

www.jianshu.com/p/834691915… www.cnblogs.com/hzmark/p/ne…

1九、在實際項目中,大家是怎麼使用Netty的?

沒用過。

20、使用過Netty遇到過什麼問題?

(1)建立兩個NioEventLoopGroup,用於邏輯隔離NIO Acceptor和NIO I/O線程

(2)儘可能不要在ChannelHandler中啓動用戶線程(解碼後用於將POJO消息派發到後端業務線程的除外)

(3)解碼要放在NIO線程調用的解碼Handler中進行,不要切換到用戶線程完成消息的解碼.

(4)若是業務邏輯操做很是簡單(純內存操做),沒有複雜的業務邏輯計算,也可能會致使線程被阻塞的磁盤操做,數據庫操做,網絡操做等,能夠直接在NIO線程上完成業務邏輯編排,不須要切換到用戶線程.

(5)若是業務邏輯複雜,不要在NIO線程上完成,建議將解碼後的POJO消息封裝成任務,派發到業務線程池中由業務線程執行,以保證NIO線程儘快釋放,處理其它I/O操做.

(6)可能致使阻塞的操做,數據庫操做,第三方服務調用,中間件服務調用,同步獲取鎖,Sleep等

(7)Sharable註解的ChannelHandler要慎用

(8)避免將ChannelHandler加入到不一樣的ChannelPipeline中,會出現併發問題.

串行執行的ChannelHandler的工做原理

從上面的隨便挑一個吹水就行。

2一、netty的線程模型,netty如何基於reactor模型上實現的。

這個網上不少了,就不說了。 www.cnblogs.com/coding400/p…

2三、netty的fashwheeltimer的用法,實現原理,是否出現過調用不夠準時,怎麼解決。

www.cnblogs.com/eryuan/p/79…

2四、netty的心跳處理在弱網下怎麼辦。

blog.csdn.net/z69183787/a…

2五、netty的通信協議是什麼樣的。

www.cnblogs.com/549294286/p…

相關文章
相關標籤/搜索