目錄
NIO
Reactor執行緒模型
#總結
为什么选择Netty
什么是TCP 粘包/拆包
透过现象分析原因
如何解决
Netty 的零拷贝
传统意义的拷贝
零拷贝的概念
Netty中的零拷貝
Netty 內部執行流程
首頁 Java java教程 Netty是什麼? Netty相關知識的深入解析

Netty是什麼? Netty相關知識的深入解析

Nov 24, 2018 pm 04:22 PM
netty

這篇文章帶給大家的內容是關於Netty是什麼? Netty相關知識的深入解析,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Netty到底是什麼

從HTTP說起

有了Netty,你可以實作自己的HTTP伺服器,FTP伺服器,UDP伺服器, RPC伺服器,WebSocket伺服器,Redis的Proxy伺服器,MySQL的Proxy伺服器等等。

我們回顧傳統的HTTP伺服器的原理

1、建立一個ServerSocket,監聽並綁定一個連接埠

2、一系列客戶端來請求這個連接埠

3、伺服器使用Accept,取得一個來自客戶端的Socket連線物件

4、啟動一個新執行緒處理連線

4.1、讀取Socket,得到位元組流

4.2、解碼協議,得到Http請求物件

4.3、處理Http請求,得到一個結果,封裝成一個HttpResponse物件

4.4、編碼協議,將結果序列化字節流寫Socket,將位元組流發給客戶端

5、繼續循環步驟3

HTTP伺服器之所以稱為HTTP伺服器,是因為編碼解碼協定是HTTP協議,如果協定是Redis協議,那它就變成了Redis伺服器,如果協定是WebSocket,那它就變成了WebSocket伺服器,等等。使用Netty你就可以自訂編解碼協議,實作自己的特定協議的伺服器。

NIO

上面有傳統處理http的伺服器,但在高並發的環境下,執行緒數量會比較多,System load也會比較高,所以就有了NIO。

他不是Java獨有的概念,NIO代表的一個詞彙叫著IO多路復用。它是由作業系統提供的系統調用,早期這個作業系統調用的名字是select,但是效能低下,後來漸漸演化成了Linux下的epoll和Mac裡的kqueue。我們通常會說是epoll,因為沒有人拿蘋果電腦當伺服器來使用對外提供服務。而Netty就是基於Java NIO技術封裝的一套架構。為什麼要封裝,因為原生的Java NIO使用起來沒那麼方便,而且還有臭名昭著的bug,Netty把它封裝之後,提供了一個易於操作的使用模式和接口,用戶使用起來也就便捷多了。

說NIO之前先說一下BIO(Blocking IO),如何理解這個Blocking呢?

客戶端監聽(Listen)時,Accept是阻塞的,只有新連線來了,Accept才會回,主執行緒才能繼

讀寫socket時,Read是阻塞的,只有請求訊息來了,Read才能返回,子執行緒才能繼續處理

讀寫socket時,Write是阻塞的,只有客戶端把訊息收了,Write才能返回,子執行緒才能繼續讀取下一個請求

傳統的BIO模式下,從頭到尾的所有執行緒都是阻塞的,這些執行緒就乾等著,佔用系統的資源,什麼事也不幹。

那麼NIO是怎麼做到非阻塞的呢。它用的是事件機制。它可以用一個執行緒把Accept,讀寫操作,請求處理的邏輯全乾了。如果什麼事都沒得做,它也不會死循環,它會將線程休眠起來,直到下一個事件來了再繼續幹活,這樣的一個線程稱之為NIO線程。用偽代碼表示:

while true {

    events = takeEvents(fds)  // 获取事件,如果没有事件,线程就休眠

    for event in events {        if event.isAcceptable {

            doAccept() // 新链接来了
        } elif event.isReadable {

            request = doRead() // 读消息

            if request.isComplete() {

                doProcess()

            }

        } elif event.isWriteable {

            doWrite()  // 写消息
        }

    }

}
登入後複製

Reactor執行緒模型

Reactor單執行緒模型

一個NIO執行緒一個accept執行緒:

Netty是什麼? Netty相關知識的深入解析

#Reactor多執行緒模型

Netty是什麼? Netty相關知識的深入解析

Reactor主從模型

主從Reactor多執行緒:多個acceptor的NIO執行緒池用於接受客戶端的連線

Netty是什麼? Netty相關知識的深入解析

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

總結

Netty是建立在NIO基礎之上,Netty在NIO之上又提供了更高層次的抽象。

在Netty裡面,Accept連線可以使用單獨的執行緒池去處理,讀寫操作又是另外的執行緒池來處理。

Accept连接和读写操作也可以使用同一个线程池来进行处理。而请求处理逻辑既可以使用单独的线程池进行处理,也可以跟放在读写线程一块处理。线程池中的每一个线程都是NIO线程。用户可以根据实际情况进行组装,构造出满足系统需求的高性能并发模型。

为什么选择Netty

如果不用netty,使用原生JDK的话,有如下问题:

1、API复杂

2、对多线程很熟悉:因为NIO涉及到Reactor模式

3、高可用的话:需要出路断连重连、半包读写、失败缓存等问题

4、JDK NIO的bug

而Netty来说,他的api简单、性能高而且社区活跃(dubbo、rocketmq等都使用了它)

什么是TCP 粘包/拆包

现象

先看如下代码,这个代码是使用netty在client端重复写100次数据给server端,ByteBuf是netty的一个字节容器,里面存放是的需要发送的数据

public class FirstClientHandler extends ChannelInboundHandlerAdapter { 
 @Override 
 public void channelActive(ChannelHandlerContext ctx) { 
 for (int i = 0; i < 1000; i++) { 
 ByteBuf buffer = getByteBuf(ctx); 
 ctx.channel().writeAndFlush(buffer); 
 } 
 } 
 private ByteBuf getByteBuf(ChannelHandlerContext ctx) { 
 byte[] bytes = "需要更多资料加群:586446657".getBytes(Charset.forName("utf-8")); 
 ByteBuf buffer = ctx.alloc().buffer(); 
 buffer.writeBytes(bytes); 
 return buffer; 
 }
}
登入後複製

从client端读取到的数据为:

Netty是什麼? Netty相關知識的深入解析

从服务端的控制台输出可以看出,存在三种类型的输出

一种是正常的字符串输出。

一种是多个字符串“粘”在了一起,我们定义这种 ByteBuf 为粘包。

一种是一个字符串被“拆”开,形成一个破碎的包,我们定义这种 ByteBuf 为半包。

透过现象分析原因

应用层面使用了Netty,但是对于操作系统来说,只认TCP协议,尽管我们的应用层是按照 ByteBuf 为 单位来发送数据,server按照Bytebuf读取,但是到了底层操作系统仍然是按照字节流发送数据,因此,数据到了服务端,也是按照字节流的方式读入,然后到了 Netty 应用层面,重新拼装成 ByteBuf,而这里的 ByteBuf 与客户端按顺序发送的 ByteBuf 可能是不对等的。因此,我们需要在客户端根据自定义协议来组装我们应用层的数据包,然后在服务端根据我们的应用层的协议来组装数据包,这个过程通常在服务端称为拆包,而在客户端称为粘包。

拆包和粘包是相对的,一端粘了包,另外一端就需要将粘过的包拆开,发送端将三个数据包粘成两个 TCP 数据包发送到接收端,接收端就需要根据应用协议将两个数据包重新组装成三个数据包。

如何解决

在没有 Netty 的情况下,用户如果自己需要拆包,基本原理就是不断从 TCP 缓冲区中读取数据,每次读取完都需要判断是否是一个完整的数据包 如果当前读取的数据不足以拼接成一个完整的业务数据包,那就保留该数据,继续从 TCP 缓冲区中读取,直到得到一个完整的数据包。 如果当前读到的数据加上已经读取的数据足够拼接成一个数据包,那就将已经读取的数据拼接上本次读取的数据,构成一个完整的业务数据包传递到业务逻辑,多余的数据仍然保留,以便和下次读到的数据尝试拼接。

而在Netty中,已经造好了许多类型的拆包器,我们直接用就好:

Netty是什麼? Netty相關知識的深入解析

选好拆包器后,在代码中client段和server端将拆包器加入到chanelPipeline之中就好了:

如上实例中:

客户端:

ch.pipeline().addLast(new FixedLengthFrameDecoder(31));
登入後複製
登入後複製

服务端:

ch.pipeline().addLast(new FixedLengthFrameDecoder(31));
登入後複製
登入後複製

Netty是什麼? Netty相關知識的深入解析

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中的零拷貝

主要體現在三個方面:

#1、bytebuffer

Netty發送和接收訊息主要使用bytebuffer,bytebuffer使用對外記憶體(DirectMemory)直接進行Socket讀寫。

原因:如果使用傳統的堆疊記憶體進行Socket讀寫,JVM會將堆疊記憶體buffer拷貝一份到直接記憶體中然後再寫入socket,多了一次緩衝區的記憶體拷貝。 DirectMemory中可以直接透過DMA傳送到網卡介面

2、Composite Buffers

傳統的ByteBuffer,如果需要將兩個ByteBuffer中的資料組合在一起,我們需要先建立一個size= size1 size2大小的新的數組,然後將兩個數組中的資料拷貝到新的數組中。但是使用Netty提供的組合ByteBuf,就可以避免這樣的操作,因為CompositeByteBuf並沒有真正將多個Buffer組合起來,而是保存了它們的引用,從而避免了數據的拷貝,實現了零拷貝。

3、對於FileChannel.transferTo的使用

Netty中使用了FileChannel的transferTo方法,該方法依賴作業系統實作零拷貝。

Netty 內部執行流程

服務端:

 Netty是什麼? Netty相關知識的深入解析

Netty是什麼? Netty相關知識的深入解析

1、建立ServerBootStrap實例

2、設定並綁定Reactor執行緒池:EventLoopGroup,EventLoop就是處理所有註冊到本執行緒的Selector上面的Channel

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

4、5、建立處理網路事件的ChannelPipeline和handler,網路時間以流的形式在其中流轉,handler完成多數的功能自訂:例如編解碼SSl安全認證

6、綁定並啟動監聽埠

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

8、說到這裡順便給大家推薦一個Java的交流學習社區:586446657,裡面不僅可以交流討論,還有面試經驗分享以及免費的資料下載,包括Spring,MyBatis,Netty源碼分析,高並發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。相信對於已經工作和遇到技術瓶頸的碼友,在這裡會有你需要的內容。

客戶端

Netty是什麼? Netty相關知識的深入解析

Netty是什麼? Netty相關知識的深入解析

#總結

以上就是我對Netty相關知識整理,如果有不同的見解,歡迎討論!

以上是Netty是什麼? Netty相關知識的深入解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java API 開發中使用 Netty4 進行 TCP 通信 Java API 開發中使用 Netty4 進行 TCP 通信 Jun 17, 2023 pm 11:18 PM

TCP是電腦網路通訊協定的一種,是一種連線導向的傳輸協定。在Java應用開發中,TCP通訊被廣泛應用於各種場景,例如客戶端和伺服器之間的資料傳輸、音訊視訊即時傳輸等等。 Netty4是一個高效能、高可擴展性、高效能的網路程式框架,能夠優化伺服器和用戶端之間的資料交換流程,使其更有效率可靠。使用Netty4進行TCP通訊的具體實作步驟如下:引入

Java開發:如何使用Netty進行高效能網路編程 Java開發:如何使用Netty進行高效能網路編程 Sep 20, 2023 pm 02:09 PM

Java開發:如何使用Netty進行高效能網路程式設計摘要:Netty是一個高效能、非同步事件驅動的網路程式框架,能夠簡化網路應用程式的開發過程。本文將介紹Netty的主要特點以及如何使用Netty進行高性能網路程式設計。同時,我們也會提供一些具體的Java程式碼範例,幫助讀者更能理解和應用Netty。一、Netty簡介Netty是一個基於JavaNIO的網路程式框

PHP實作開源Netty框架 PHP實作開源Netty框架 Jun 18, 2023 pm 07:03 PM

隨著網路科技的不斷發展,網路程式設計變得越來越重要。在這個領域中,Netty是一個十分知名的框架。它是一個高效能、非同步事件驅動的網路應用程式框架,被廣泛用於開發各種高並發的網路應用程式。 Netty是一個Java框架,它的產生推動了Java網路程式設計的發展。然而,隨著PHP的廣泛使用,PHP開發者也在尋找能夠勝任高並發網路程式設計的框架。因此,本文介紹如何利用P

springboot整合netty框架的方式有哪些 springboot整合netty框架的方式有哪些 May 10, 2023 pm 09:55 PM

netty作為一個高效能的io框架,是非好用的一個技術框架,Netty是一個基於NIO的客戶、伺服器端程式設計框架,使用Netty可以確保你快速且簡單的開發出一個網路應用,例如實現了某種協定的客戶、服務端應用。 Netty相當於簡化和流線化了網路應用的程式開發過程,例如:基於TCP和UDP的socket服務開發。 「快速」和「簡單」並不用產生維護性或效能上的問題。 Netty是個吸收了多種協定(包括FTP、SMTP、HTTP等各種二進位文字協定)的實作經驗,並經過相當精心設計的專案。最終,Netty成功

Java後端開發:使用Netty建置高並發API伺服器 Java後端開發:使用Netty建置高並發API伺服器 Jun 17, 2023 am 10:23 AM

隨著互聯網的不斷發展和應用領域的不斷擴展,高並發成為了網絡應用開發中必須考慮的問題,而Java作為一種廣泛應用於企業級應用開發的語言,其在高並發應用場景下的表現備受關注。 Netty是一款高效能、非同步事件驅動的網路應用框架,近年來在Java後端開發領域享有廣泛的應用。本文將介紹Netty的基本概念和使用方法,並以建立高同時的API伺服器為例,展示Netty

如何使用Java開發一個基於Netty的高效能網頁應用 如何使用Java開發一個基於Netty的高效能網頁應用 Sep 20, 2023 pm 12:21 PM

如何使用Java開發一個基於Netty的高效能網路應用Netty是一種基於JavaNIO技術的網路程式框架,被廣泛應用於高效能的網路應用開發。在本文中,我們將探討如何使用Java和Netty來開發一個基於Netty的高效能網路應用。我們將介紹Netty的基本概念和特性,並提供一些程式碼範例以幫助你更好地理解和使用Netty。一、Netty的基本概念與特性Ne

Java API 開發中使用 Netty 進行 TCP 通信 Java API 開發中使用 Netty 進行 TCP 通信 Jun 18, 2023 pm 11:34 PM

JavaAPI開發中使用Netty進行TCP通訊在現代軟體開發中,網路通訊已成為不可或缺的一部分。 Netty是一種Java框架,用於在高效能網路應用中有效地進行快速開發。它提供了一組易於使用的API,封裝了JavaNIO和其他網路庫。在JavaAPI開發中,Netty的優越性可以體現在以下幾個方面:高性能Netty的應用程式

Java API 開發中使用 Netty5 進行 TCP 通信 Java API 開發中使用 Netty5 進行 TCP 通信 Jun 18, 2023 am 08:31 AM

在JavaAPI開發中,TCP通訊是一個非常重要的元件,而Netty5是一套基於NIO的高效能網路通訊框架,可以非常方便地處理複雜的網路通訊任務。本文將介紹如何使用Netty5進行TCP通信,包括Netty5的核心元件、常用API的介紹和實際應用案例。同時,本文也將介紹如何使用Netty5來提高TCP通訊的效能和可靠性。一、Netty5的核心組件Netty5

See all articles