天天看點

Netty了解與小試

在網際網路的應用中有一個特點,高并發,但處理邏輯相對簡單。針對這個特别有時間我們可以相對的簡化下平時所有的WEB伺服器,來滿足這一的特點,而且更友善控制。Netty就是一個不錯的選擇,Netty 提供異步的、事件驅動的網絡應用程 另外與Spring一起使用,以快速開發高性能、高可靠性的網絡伺服器和用戶端程式。

最近的一個項目使用了這點,不錯的解決了這類的應用。下面是在了解這方面的時間找到的不錯的資料。

netty是JBOSS針對網絡開發的一套應用架構,它也是在NIO的基礎上發展起來的。netty基于異步的事件驅動,具有高性能、高擴充性等特性,它提供了統一的底層協定接口,使得開發者從底層的網絡協定(比如 TCP/IP、UDP)中解脫出來。就使用來說,開發者隻要參考 Netty提供的若幹例子和它的指南文檔,就可以放手開發基于Netty的服務端程式了。

   netty有幾個比較重要的概念,在此,僅做介紹,詳細可以參考netty文檔或源碼。

   1). channelBuffer: 是 Netty 的一個基本資料結構,這個資料結構存儲了一個位元組序列。 類似于 NIO 的 ByteBuffer,但操作起來比ByteBuffer更為簡單友善。

   2). ChannelFactory 是一個建立和管理 Channel 通道及其相關資源的工廠接口,它處理所有的 I/O 請求并産生相應的 I/O ChannelEvent 通道事件。

  3).ChannelHandler是所有I/O ChannelEvent事件的響應類,所有消息,包括netty通信異常事件,均在該響應類内處理。

  4).*** Bootstrap 是一個設定服務的幫助類。你甚至可以在這個服務中直接設定一個 Channel 通道。

  現在以實作一個UDP協定下的伺服器應用程式為例,示範netty通過spring注解開發伺服器端。(在此以maven工具管理項目開發)

<a href="http://blog.csdn.net/tanrenzong1986/article/details/6404256">http://blog.csdn.net/tanrenzong1986/article/details/6404256</a>

netty的性能非常高,能達到8000rps以上,見

<a href="http://blog.chinaunix.net/uid-11121450-id-3147009.html">http://blog.chinaunix.net/uid-11121450-id-3147009.html</a>

Netty一般都通過bootStrap來啟動, 網絡動作過程就是伺服器端bind-&gt;accept-&gt;read-&gt;write,用戶端 connect-&gt;read-&gt;write,一般bind或者connect後會有多次read、write。依據這種特性netty将bind,accept與read,write的線程分離,connect與read、write線程分離

一、Netty主要可以分為3部分: buffer, channel, handle。

1、      Channelbuffer

l  所有的實作類中都提供,readerIndex, writerIndex兩個指針,無需nio buffer的flip.

l  可以通過ChannelBufferFactory來建立channelbuffer. 分為兩類buffer

 HeapChannelBufferFactory: 在jvm堆上建立緩沖區,預設是BIG_ENDIAN排序

DirectChannelBufferFactory:對應nio ByteBuffer.allocateDirect(),直接緩沖區配置設定

l  WrappedChannelBuffer實作對ChannelBuffer封裝,通過其可以自定義channelbuffer.

2、      Channel:

通常每種類型的channel一般都有一個對應channelfactory類,以及一個channelconifg類。  通過channelfactory建立channel執行個體,然後由channelconifg來配置channel屬性。

l  ChannelGroup:  一組通道的集合,線程安全, 關閉的通道會自動從集合中删除, 可以通過ChannelGroup廣播消息。

l  Channel的種類:

LocalChannel、 LocalServerChannel:本地通道、虛拟一個網絡。

DatagramChanneel: udp連接配接通道.

ServerSocketChannel、SoketChannel:  處理tcp/ip連接配接的通道。

l  Channelevent:  用于将:channel的相關資訊 如channel本身,傳遞的資料,channel的狀态, future等等一起打包,在調用org.jboss.netty.channel.Channels類的各個靜态的fire方式中産生,然後在channelpipe中的sendUpsteam或sendDownStream中傳遞。

l  ChannelSink:處理pipeline中downstream結束後的事件。

3、      handler:

所有需要調用的handler都被包裝成ChannelHandlerContext,注冊到channelpipeline的一個map中,  通過兩個指針:head和tail保證map中的handle的調用順序。處理upstream時,通過head指針從前往後依次調用實作ChannelUpstreamHandler接口的handle.   downstream處理通過tail指針,從後往前依次調用實作ChannelDownstreamHandler接口的handle。  在downsream的channelpipeline傳送完後,ChannelSink的eventSunk方法完成對系統底層的調用處理。(ChannelSink和channel是通過attach的方式綁定到channelpipeline上)

Netty中已經提供的handler的種類如下:

l  codec handle。包括  64位機器的編碼、解碼,   字元集轉化,壓縮,http請求編碼、解碼; 序列化對象的編碼、解碼等等。通過codec handle我們可以直接往channel中寫java 對象。

l  Timeout handler通過jboss.netty.util.Timer來對讀寫逾時或者閑置連結的通知,在handle中建立一個time對象,這個time對象包含一個定時器線程Work程序,在handle第一次被觸發時,啟動一個Work線程:監控逾時事件。

l  Stream handler  用于異步處理大資料傳遞。通過将java.io.file對象包裝成ChunkedFile對象,進行傳遞,ChunkedFile的底層實作是RandomAccessFile.

l  Queue handler: 使用者将接受到的資料或需要發送的資料先存儲到一個queue隊列中,然後一次性的讀和寫。  包括BlockingReadHandler和BufferedWriteHandler. 注意在BlockingReadHandler将receivemessage存儲入queue後,其後的handler将不再處理 messageReceived,exceptionCaught 和channelClosed事件,是以BlockingReadHandler必須放在channelpipeline的最後。  同理BufferedWriteHandler。

4、      其他

l  org.jboss.netty.container 各種容器的相容 Microcontainer OSGi Spring framework 整合接口

l  Bootstrap 啟動類: BootStrap: TCP伺服器端啟動; ClientBootStrap:Tcp client端啟動和ConnectionlessBootstrap  UDP啟動。

二、伺服器的啟動和客服端connect的過程

1 、伺服器啟動

 bootstrap.bind(…)-&gt; 觸發ServerSocketChannel.open()的事件(sendupstream)-&gt;捕捉open事件,channel.bind-&gt; Channels.bind(…)  發起bind指令(sendDownstream)-&gt; PipelineSink進行處理-&gt; 使用socket進行bind,啟動boss程序。

 Boostrap.bind 方法包含兩個參數NioServerSocketChannelFactory、ChannelPipelineFactory。NioServerSocketChannelFactory包含連個線程池bossExecutor和workerExecutor,workerExecutor: 包含預設為處理器個數×2個NioWorker程序。

 2、伺服器處理連接配接

 Boss啟動後,在監聽accept事件, 将捕獲到的事件作為一個task放到一個niowork程序

的registerTaskQueue隊列中。

3、伺服器端接收并處理資料

  NioWorker.run()-&gt;nioworker. processSelectedKeys()-&gt;Nioworker. Read()将從SocketChannel讀取的資料封裝成ChannelBuffer -&gt;調用fireMessageReceived(channel,buffer)産生upstream事件 –&gt; 由注冊到Pipeline中的Hanlder進行處理

4、用戶端connection

同伺服器啟動一樣也需要建立一個NioClientSocketChannelFactory和一個ChannelPipelineFactory。  同伺服器端不同的是client端的boss程序不要監聽,它将本地發出的建立的連結的請求封裝成task放入一個registerTaskQueue,boss負責消費Queue隊列中的消息。

<a href="http://blog.csdn.net/north_eagle/article/details/6545357">http://blog.csdn.net/north_eagle/article/details/6545357</a>

本文轉自茄子_2008部落格園部落格,原文連結:http://www.cnblogs.com/xd502djj/archive/2012/06/25/2561318.html,如需轉載請自行聯系原作者。