"Turn" netty that thing. (iii) pipeline in the channel

Source: Internet
Author: User

"Original" https://github.com/code4craft/netty-learning/blob/master/posts/ch3-pipeline.md

Channel is the core of understanding and using Netty. The channel involves a lot of content, here I use the introduction method of the way. In this article, we mainly introduce the pipeline implementation mechanism in the channel section. In order to avoid boring, borrow "dream space" of "dream" concept, I hope you like.

A Dream: Channel implementation overview

In Netty, Channel it is the carrier of communication, which is ChannelHandler responsible for the logic processing in the channel.

So ChannelPipeline what is it? I think it can be understood as a Channelhandler container: A channel contains a channelpipeline, and all Channelhandler are registered in Channelpipeline and organized sequentially.

In Netty, ChannelEvent is the carrier of the data or the state, for example the data of the transmission corresponds MessageEvent , the change of the state corresponds ChannelStateEvent . When the channel is operated, a channelevent is generated and sent to the ChannelPipeline . Channelpipeline will select a channelhandler for processing. After this channelhandler is processed, new channelevent may be generated and transferred to the next Channelhandler.

For example, a data is initially a MessageEvent , it comes with a raw binary message that is not decoded ChannelBuffer , and then a handler decodes it into a data object, generates a new one MessageEvent , and passes it to the next process.

Here, you can see that the core process of the channel is ChannelPipeline in. So we go into the deep dream of channelpipeline, and look at its concrete realization.

Two-story dream: The main course of Channelpipeline

Netty's channelpipeline consists of two lines: upstream and downstream. Upstream corresponds to the upstream, received the message, the passive state change, all belong to upstream. Downstream the corresponding downlink, the message sent, the active state change, all belong to downstream. The ChannelPipeline interface contains two important methods: sendUpstream(ChannelEvent e) and sendDownstream(ChannelEvent e) , respectively, corresponds to upstream and downstream.

Corresponding, the channelhandler contained in the Channelpipeline also contains two categories: ChannelUpstreamHandler and ChannelDownstreamHandler . The handler of each line is independent of one another. They are simple enough to contain only one method: ChannelUpstreamHandler.handleUpstream and ChannelDownstreamHandler.handleDownstream .

Netty Official Javadoc There is a picture (in the ChannelPipeline interface), the very image of this mechanism (I made a little change to the original, plus ChannelSink , because I think this part of the understanding of the code process will be some help):

What do you call ChannelSink it? Channelsink contains an important method ChannelSink.eventSunk that can accept arbitrary channelevent. "Sink" means "sinking", then "Channelsink" seems to be understood as "where the channel sinks"? In fact, it does so, or it can be said: "At the end of the almighty handler." When I first read about it, it was a bit confusing and it was a lot easier to understand. only downstream included ChannelSink , here are some important operations such as establishing connections, binding ports, and so on. Why Uploadstream no Channelsink? I can only think, on the one hand, is not in line with the meaning of "sink", on the other hand, there is nothing to do with it!

Here's a note: in a "flow", a "stream" that ChannelEvent does not take the initiative is generated by all handler, but by an explicit invocation of the previous handler ChannelPipeline.sendUp(Down)stream , and handed over to the next handler processing . That is, each handler receives a channelevent, and after processing is finished, if it needs to continue processing, then it needs to invoke sendUp(Down)stream a new event to be initiated. If it no longer initiates the event, then the process ends, even if there is still handler behind it. This mechanism guarantees maximum flexibility and, of course, has stricter requirements for the sequencing of handler.

By the way, in Netty 3.x, this mechanism causes a large number of Channelevent objects to be created, so the Netty 4.x version has been improved. In the Finagle framework practice of Twitter, it is mentioned that upgrading from Netty 3.x to Netty 4.x can significantly reduce GC overhead. Interested to see this article: Https://blog.twitter.com/2013/netty-4-at-twitter-reduced-gc-overhead

Below we from the code level to do in-depth analysis of what is happening in this part, which involves some details, the need to open the project source code, compared to see, will be more fruitful.

Three-storey dream: deep inside channelpipeline internal defaultchannelpipeline structure

ChannelPipelineThe main implementation code is in the DefaultChannelPipeline class. Make a list of the main fields of Defaultchannelpipeline:

    PublicClassDefaultchannelpipelineImplementsChannelpipeline{PrivateVolatileChannelChannel;PrivateVolatileChannelsinksinkprivate volatile defaultchannelhandlercontext  Headprivate volatile defaultchannelhandlercontext  Tailprivate final map<String< Span class= "O", defaultchannelhandlercontext> name2ctx = new hashmap<string defaultchannelhandlercontext> (4               /span>                

This interface needs to be introduced here ChannelHandlerContext . As the name implies, Channelhandlercontext preserves the contextual information associated with Netty handler. What we have here DefaultChannelHandlerContext is a package of the right ChannelHandler one. An DefaultChannelHandlerContext internal, in addition to a containing one ChannelHandler , also holds "next" and "prev" two pointers, thus forming a doubly linked list.

So, in DefaultChannelPipeline , we see a reference to the right DefaultChannelHandlerContext , not ChannelHandler a direct reference to it. This includes two references for "head" and "tail", pointing to the head and tail of the linked list, respectively. Name2ctx, however, is a map of defaultchannelhandlercontext users indexed by name, which is primarily used when deleting or adding Channelhandler by name.

Sendupstream and Senddownstream

As mentioned earlier, ChannelPipeline two important methods of the interface are: sendUpstream(ChannelEvent e) and sendDownstream(ChannelEvent e) . The initiation of all events is based on these two methods. Channelsclasses have a series fireChannelBound of such fireXXXX methods, in fact, are the two methods of facade packaging.

Let's look at the implementation of these two methods. First Look at Sendupstream (some simplification of the code, preserving the main logic):

    PublicvoidSendupstream(ChanneleventE){DefaultchannelhandlercontextHead=Getactualupstreamcontext(This.Head);Head.GetHandler().Handleupstream(Head,E);}PrivateDefaultchannelhandlercontextGetactualupstreamcontext(DefaultchannelhandlercontextAt) {defaultchannelhandlercontext realCtx = ctxwhile  (! Realctx.{realctx =  Realctx.if  (realctx == null {return null} } return realctx              /span>                 

The

Here finally calls the Channelupstreamhandler.handleupstream to handle this channelevent. Interestingly, we do not see any "move handler backwards one" operation, but we can not always use the same handler to deal with AH? In fact, we are more commonly used by the Channelhandlercontext.handleupstream method (Implementation is Defaultchannelhandlercontext.sendupstream method):

    Sendupstream(egetactualupstreamcontext(this.  Nextdefaultchannelpipeline.  This.  Sendupstream(nexte}           

As you can see, the method is still called here ChannelPipeline.sendUpstream , but it will move the handler pointer back .

Let's look at the following DefaultChannelHandlerContext.sendDownstream :

    PublicvoidSenddownstream(ChanneleventE){DefaultchannelhandlercontextPrev=Getactualdownstreamcontext(This.Prev);If(Prev==Null){Try{Getsink().Eventsunk (defaultchannelpipeline. Thise} catch  (throwable t ) {notifyhandlerexception (e< Span class= "O", t} } else {defaultchannelpipeline< Span class= "O". this. (preve} }             /span>                

It doesn't seem to be the same with Sendupstream, huh? Here are two points: first, when you reach the end, as in Dream Two, you call channelsink for processing, and the pointer moves forward , so we know:

Upstreamhandler is carried out from the back, and Downstreamhandler is executed from the back forward. you need to pay attention to the order when you add it in Channelpipeline!

There are some mechanisms in defaultchannelpipeline, such as adding/removing/replacing handler, and ChannelPipelineFactory so on, a better understanding, not to elaborate.

Back to reality: Pipeline solves the problem

Well, in-depth analysis of the code, a little dizzy, we go back to the beginning of the place, to think, Netty pipeline mechanism to solve what problem?

I think there are at least two points:

One is to provide Channelhandler programming model, based on Channelhandler development business logic, basically do not need to care about the network communication aspects, focus on coding/decoding/logic processing on it. Handler is also a more convenient development model, which is useful in many frameworks.

The second is to realize the so-called "Universal asynchronous API". This is also a feature that Netty officially advertised. Both Oio and NiO know that the two sets of API styles are vastly different, and that moving from one to the other costs a lot. Even NiO, there is a large gap between asynchronous and synchronous programming. The Netty shielded the API differences between OIO and NIO, providing an external interface through the channel and connecting it through Channelpipeline, so it's easy to replace.

Having cleared up the mainstream of channelpipeline, we have figured out the approximate structure of the channel section. But here, we still have a connection to the specific how to deal with no concept, the next article, we will analyze, in the Netty, the shortcut how to deal with the establishment of connections, data transmission these things.

Ps:pipeline This part dragged for two months, finally finished. Writing in the middle is slow, write a high quality (at least think it!). Article is not easy, but still do not bear this part of this rotten tail. Some of the best articles are referenced in the middle, and some applications have been developed using Netty. After this kind of article, still want to concentrate time to write intact.

Resources:

    • Sink HTTP://EN.WIKIPEDIA.ORG/WIKI/SINK_ (computing)

"Turn" netty that thing. (iii) pipeline in the channel

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.