在互聯網的應用中有一個特點,高併發,但處理邏輯相對簡單。針對這個特別有時間我們可以相對的簡化下平時所有的WEB服務器,來滿足這一的特點,而且更方便控制。Netty就是一個不錯的選擇,Netty 提供異步的、事件驅動的網絡應用程 另外與Spring一起使用,以快速開發高性能、高可靠性的網絡服務器和客戶端程序。
最近的一個項目使用了這點,不錯的解決了這類的應用。下面是在瞭解這方面的時間找到的不錯的資料。
http://wenku.baidu.com/view/7765bc2db4daa58da0114a4c.html 深入淺出Netty
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工具管理項目開發)
http://blog.csdn.net/tanrenzong1986/article/details/6404256
netty的性能非常高,能達到8000rps以上,見
http://blog.chinaunix.net/uid-11121450-id-3147009.html
Netty一般都通過bootStrap來啓動, 網絡動作過程就是服務器端bind->accept->read->write,客戶端 connect->read->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(…)-> 觸發ServerSocketChannel.open()的事件(sendupstream)->捕捉open事件,channel.bind-> Channels.bind(…) 發起bind命令(sendDownstream)-> PipelineSink進行處理-> 使用socket進行bind,啓動boss進程。
Boostrap.bind 方法包含兩個參數NioServerSocketChannelFactory、ChannelPipelineFactory。NioServerSocketChannelFactory包含連個線程池bossExecutor和workerExecutor,workerExecutor: 包含缺省爲處理器個數×2個NioWorker進程。
2、服務器處理連接
Boss啓動後,在監聽accept事件, 將捕獲到的事件作爲一個task放到一個niowork進程
的registerTaskQueue隊列中。
3、服務器端接收並處理數據
NioWorker.run()->nioworker. processSelectedKeys()->Nioworker. Read()將從SocketChannel讀取的數據封裝成ChannelBuffer ->調用fireMessageReceived(channel,buffer)產生upstream事件 –> 由註冊到Pipeline中的Hanlder進行處理
4、客戶端connection
同服務器啓動一樣也需要創建一個NioClientSocketChannelFactory和一個ChannelPipelineFactory。 同服務器端不同的是client端的boss進程不要監聽,它將本地發出的建立的鏈接的請求封裝成task放入一個registerTaskQueue,boss負責消費Queue隊列中的消息。