Netty源碼學習——ChannelPipeline模型分析

來源:互聯網
上載者:User

標籤:nio   io   netty   

參考Netty API
io.netty.channel.ChannelPipeline

A list of ChannelHandlers which handles or intercepts inbound events and outbount operations of aChannel.ChannelPipeline implements an advanced form of theIntercepting Filter pattern to give a user full control over how an event is handled and how theChannelHandlers in a pipeline interact with each other.

Creation of a pipelineEach channel has its own pipeline and it is created automatically when a new channel is created.How an event flows in a pipeline

The following diagram describes how I/O events are processed by ChannelHandlers in aChannelPipeline typically. An I/O event is handled by either aChannelInboundHandler or aChannelOutboundHandler and be forwarded to its closest handler by calling the event propagation methods defined inChannelHandlerContext, such asChannelHandlerContext.fireChannelRead(Object) andChannelHandlerContext.write(Object).

                                                 I/O Request                                            via Channel or                                        ChannelHandlerContext                                                      |  +---------------------------------------------------+---------------+  |                           ChannelPipeline         |               |  |                                                  \|/              |  |    +---------------------+            +-----------+----------+    |  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |  |    +----------+----------+            +-----------+----------+    |  |              /|\                                  |               |  |               |                                  \|/              |  |    +----------+----------+            +-----------+----------+    |  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |  |    +----------+----------+            +-----------+----------+    |  |              /|\                                  .               |  |               .                                   .               |  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|  |        [ method call]                       [method call]         |  |               .                                   .               |  |               .                                  \|/              |  |    +----------+----------+            +-----------+----------+    |  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |  |    +----------+----------+            +-----------+----------+    |  |              /|\                                  |               |  |               |                                  \|/              |  |    +----------+----------+            +-----------+----------+    |  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |  |    +----------+----------+            +-----------+----------+    |  |              /|\                                  |               |  +---------------+-----------------------------------+---------------+                  |                                  \|/  +---------------+-----------------------------------+---------------+  |               |                                   |               |  |       [ Socket.read() ]                    [ Socket.write() ]     |  |                                                                   |  |  Netty Internal I/O Threads (Transport Implementation)            |  +-------------------------------------------------------------------+ 


                                                                                                                                  Figure 1

An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the diagram. The inbound data is often read from a remote peer via the actual input operation such as SocketChannel.read(ByteBuffer). If an inbound event goes beyond the top inbound handler, it is discarded silently, or logged if it needs your attention.

An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests. If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the Channel. The I/O thread often performs the actual output operation such asSocketChannel.write(ByteBuffer).

For example, let us assume that we created the following pipeline:

 ChannelPipeline p = ...; p.addLast("1", new InboundHandlerA()); p.addLast("2", new InboundHandlerB()); p.addLast("3", new OutboundHandlerA()); p.addLast("4", new OutboundHandlerB()); p.addLast("5", new InboundOutboundHandlerX()); 
In the example above, the class whose name starts with Inbound means it is an inbound handler. The class whose name starts with Outbound means it is a outbound handler.

In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound. When an event goes outbound, the order is 5, 4, 3, 2, 1. On top of this principle,ChannelPipeline skips the evaluation of certain handlers to shorten the stack depth:

  • 3 and 4 don‘t implement ChannelInboundHandler, and therefore the actual evaluation order of an inbound event will be: 1, 2, and 5.
  • 1 and 2 implement ChannelOutboundHandler, and therefore the actual evaluation order of a outbound event will be: 5, 4, and 3.
  • If 5 implements both ChannelInboundHandler andChannelOutboundHandler, the evaluation order of an inbound and a outbound event could be 125 and 543 respectively.
Forwarding an event to the next handlerAs you might noticed in the diagram shows, a handler has to invoke the event propagation methods in ChannelHandlerContext to forward an event to its next handler. Those methods include:
  • Inbound event propagation methods:
    • ChannelHandlerContext.fireChannelRegistered()
    • ChannelHandlerContext.fireChannelActive()
    • ChannelHandlerContext.fireChannelRead(Object)
    • ChannelHandlerContext.fireChannelReadComplete()
    • ChannelHandlerContext.fireExceptionCaught(Throwable)
    • ChannelHandlerContext.fireUserEventTriggered(Object)
    • ChannelHandlerContext.fireChannelWritabilityChanged()
    • ChannelHandlerContext.fireChannelInactive()
    • ChannelHandlerContext.fireChannelUnregistered()
  • Outbound event propagation methods:
    • ChannelHandlerContext.bind(SocketAddress, ChannelPromise)
    • ChannelHandlerContext.connect(SocketAddress, SocketAddress, ChannelPromise)
    • ChannelHandlerContext.write(Object, ChannelPromise)
    • ChannelHandlerContext.flush()
    • ChannelHandlerContext.read()
    • ChannelHandlerContext.disconnect(ChannelPromise)
    • ChannelHandlerContext.close(ChannelPromise)
    • ChannelHandlerContext.deregister(ChannelPromise)
and the following example shows how the event propagation is usually done:
 public class MyInboundHandler extends ChannelInboundHandlerAdapter {     @Override     public void channelActive(ChannelHandlerContext ctx) {         System.out.println("Connected!");         ctx.fireChannelActive();     } } public clas MyOutboundHandler extends ChannelOutboundHandlerAdapter {     @Override     public void close(ChannelHandlerContext ctx, ChannelPromise promise) {         System.out.println("Closing ..");         ctx.close(promise);     } } 
Building a pipeline

A user is supposed to have one or more ChannelHandlers in a pipeline to receive I/O events (e.g. read) and to request I/O operations (e.g. write and close). For example, a typical server will have the following handlers in each channel‘s pipeline, but your mileage may vary depending on the complexity and characteristics of the protocol and business logic:

  1. Protocol Decoder - translates binary data (e.g. ByteBuf) into a Java object.
  2. Protocol Encoder - translates a Java object into binary data.
  3. Business Logic Handler - performs the actual business logic (e.g. database access).
and it could be represented as shown in the following example:
 static final EventExecutorGroup group = new DefaultEventExecutorGroup(16); ... ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new MyProtocolDecoder()); pipeline.addLast("encoder", new MyProtocolEncoder()); // Tell the pipeline to run MyBusinessLogicHandler‘s event handler methods // in a different thread than an I/O thread so that the I/O thread is not blocked by // a time-consuming task. // If your business logic is fully asynchronous or finished very quickly, you don‘t // need to specify a group. pipeline.addLast(group, "handler", new MyBusinessLogicHandler()); 
Thread safety

A ChannelHandler can be added or removed at any time because aChannelPipeline is thread safe. For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it after the exchange.

—————>>>>>>>>>>>>>>>>>>華麗的分界線<<<<<<<<<<<<<<<<<—————————————

Figure1 變形:

    +-------------------------------------------------------------------+  |                                IN                                 |  |                                 |                                 |  |                                 |                                 |  |                          [(Socket)read]                           |  |                                 |                                 |  |                                 |                                 |  |                                \|/                                |  |                      +----------+----------+                      |  |                      | Inbound Handler  1  |                      |  |                      +----------+----------+                      |  |                                 |                                 |  |                                \|/                                |  |                      +----------+----------+                      |  |                      | Inbound Handler  2  |                      |  |                      +----------+----------+                      |  |                                 .                                 |  |                                 .                                 |  |                                \./                                |  |                   ChannelHandlerContext.FireIN_EVT                |         |                           [ method call]                          |  |                                 .                                 |  |                                 .                                 |  |                                \./                                |      |                      +----------+----------+                      |  |                      | Inbound Handler N-1 |                      |  |                      +----------+----------+                      |  |                                \|/                                |                                                                                                                 |                                 |                                 |  |                      +----------+----------+                      |  |                      | Inbound Handler  N  |                      |  |                      +----------+----------+                      |  |                                 |                                 |  |                                \|/                                |  |                                 |                                 |  +---------------------------------+---------------------------------+  |                                 |                                 |  |                                 |                                 |  |                            Application                            |  |                                 |                                 |  |                                 |                                 |  +---------------------------------+---------------------------------+  |                                 |                                 |  |                                \|/                                |  |                     +-----------+----------+                      |  |                     | Outbound Handler  1  |                      |  |                     +-----------+----------+                      |  |                                 |                                 |  |                                \|/                    |                     +-----------+----------+                      |  |                     | Outbound Handler  2  |                      |  |                     +-----------+----------+                      |  |                                 .                                 |  |                                 .                                 |  |                                \./                                |  |                   ChannelHandlerContext.OUT_EVT()                 |  |                           [ method call]                          |  |                                 .                                 |  |                                 .                                 |  |                                \./                                |   |                     +-----------+----------+                      |  |                     | Outbound Handler M-1 |                      |  |                     +-----------+----------+                      |  |                                 |                                 |  |                                \|/                                |  |                     +-----------+----------+                      |  |                     | Outbound Handler  M  |                      |  |                     +-----------+----------+                      |  |                                 |                                 |  |                                \|/                                |  |                          [(Socket)write]                          |  |                                 |                                 |  |                                 |                                 |  |                                \|/                                |  |                                 |                                 |  |                                OUT                                |  +---------------+-----------------------------------+---------------+ 

責任鏈模式:

在閻宏博士的《JAVA與模式》一書中開頭是這樣描述責任鏈(Chain of Responsibility)模式的:

  責任鏈模式是一種對象的行為模式。在責任鏈模式裡,很多個物件由每一個對象對其下家的引用而串連起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的用戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響用戶端的情況下動態地重新組織和分配責任。

責任鏈模式涉及到的角色如下所示:

  ●  抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類別或者Java介面實現。中Handler類的彙總關係給出了具體子類對下家的引用,抽象方法handleRequest()規範了子類處理請求的操作。

  ●  具體處理者(ConcreteHandler)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。

Java website development中的filter也是責任鏈模式!

參考文章:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html;


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.