【Chapter 3 Netty from the ground up】
Netty的核心组件:

  • Bootstrap or ServerBootstrap:
    Bootstrap用于配置客户端和基于UDP协议的客户端和服务器;而ServerBootstrap只用于配置服务器. The second difference is perhaps the most important. Client bootstraps/applications use a single EventLoopGroup whilst ServerBootstrap uses 2 (which in fact can be the same instance). It may not be immediately obvious as to why this would be but it s a good reason. A ServerBootstrap can be thought to have two sets of channels. The first set containing a
    single ServerChannel representing the server s own socket which has been bound to a local port. And the second set containing all the Channel representing the connections, which the server has accepted.
  • EventLoop(类似于线程):
    An EventLoop(s) purpose in the application is to process IO operations for a Channel. A single EventLoop will typically handle events for multiple Channels. Think of EventLoops as the threads that perform the actual work for achannel. The EventLoop is always bound to a single Thread that never changed during it s life time.(即,Thread和EventLoop一一对应,一个EventLoop处理多个Channel)
  • EventLoopGroup(类似于线程池):
    The EventLoopGroup itself may contain more then one EventLoop and can be used to obtain an EventLoop.
  • ChannelPipeline:
  • Channel:
  • Future or ChannelFuture:
  • ChannelInitializer:
    The role of the ChannelInitializer is to add ChannelHandler implementations to what s called the ChannelPipeline.
  • ChannelHandler:
    One very common type you ll be writing is an implementation of the
    ChannelInboundHandler. The ChannelInboundHandler receives messages which you can process and decide what to do with it. You may also write/flush data out from inside an ChannelInboundHandler when your application needs to provide a response. In other words, the business logic of your application typically lives in a ChannelInboundHandler.

All IO operations in Netty are performed asynchronously. So when you connect to a host for example, this is done asynchronously by default. The same is true when you write/send a message. This means the operation may not be performed directly but picked up later for
execution. Because of this you can t know if an operation was successful or not after it returns, but need to be able to check later for success or have some kind of ways to register a listener
which is notified. To rectify this, Netty uses Futures and ChannelFutures. This future can be used to register a listener, which will be notified when an operation has either failed or
completed successfully.

So basically a ChannelFuture is a placeholder for a result of an operation that is executed in the future. When exactly it is executed depends on many facts and is not easy to say. The only thing you can be sure of is that it will be executed and all operations that return a ChannelFuture and belong to the same Channel will be executed in the correct order, which is the same order as you executed the methods.
即,FutureTask代表的计算(I/O操作)什么时候开始执行、什么时候执行完毕是无法确定的(因为这些操作都是异步的,异步方法调用会直接返回);唯一可以确定的是同一个Channel中的FutureTask会按照代码的执行循序顺序执行

When a channel is registered, Netty binds that channel to a single EventLoop (and so to a single thread) for the lifetime of that Channel. This is why your application doesn t need to synchronize on Netty IO operations because all IO for a given Channel will always be performed by the same thread.
即,一个Channel的整个生命周期一直只和同一个EventLoop(即一个Thread)绑定,所以对于Channel的IO操作不需要synchronization;但是如果Handler被多个Channel共用,Handler本身必须是线程安全的,因为不同的Channel可能由不同的EventLoop处理. 此外,因为多个Channel一般会共用一个EventLoop,如果EventLoop处理某个Channel时阻塞了(如使用JDBC访问数据库,这是一个阻塞操作),会使得其他Channel得不到及时处理,所以一定不要在EventLoop中阻塞

clipboard.png
上面的类图说明了,EventLoop is-a EventLoopGroup. This means wherever
you can pass in an EventLoopGroup you can also just use a specific EventLoop.

ChannelHandler接口的hierarchy:
clipboard.png

Event和数据在ChannelPipeline中的处理:
clipboard.png

An event can be forward to the next ChannelInbound or prev ChannelOutboundHandler in the ChannelPipeline by using the ChanneHandlerContext passed in to each method. Because this is what you usually want for events that you are not interested in Netty provides abstract base classes called ChannelInboundHandlerAdapter and ChannelOutboundHandlerAdapter. Each of this provide implementations for each method and just pass the event to the next/prev handler in the ChannelPipeline by call the corresponding method on the ChannelHandlerContext. You can then override the method in question to actually do the handling of you need to.

There are two ways of sending messages in Netty. You can write directly to the channel or write to the ChannelHandlerContext object. The main difference between the two is that writing to the channel directly causes the message to start from the tail of the
ChannelPipeline where as writing to the context object causes the message to start from the next handler in the ChannelPipeline.

【P48】
3.5 Encoders, Decoders and Domain Logic: A Closer Look at Handlers


bedew
278 声望3 粉丝