理解Channel、EventLoop的关系

Channel

基本的IO操作(bind、connect、read、write、accept)依赖于底层网络传输所提供的原语。在基于Java的网络编程中,其基本的构造是Socket。Netty的Channel接口所提供的API,大大降低了使用Socket类的复杂性。

此外,Channel也是拥有许多预定义的,专门化实现的广泛类层次结构的根,下面时一个简短的部分清单:

  • EmbeddedChannel
  • LocalServerChannel
  • NioDatagramChannel
  • NioSctpChannel
  • NioSocketChannel

(这部分内容接触的比较少,还不是很理解)

每个Channel都将会被分配一个ChannelPipeline和ChannelConfig。ChannelConfig包含了该Channel的所有配置设置,并且支持热更新。由于特定的传输类型可能具有独特的设置,所以它可能会实现一个ChannelConfig的子类型(我是第一次接触ChannelConfig)。

Channel的其他方法:

  • eventLoop:返回分配给Channel的EventLoop(不知道怎么利用这个)

  • pipeline:返回分配给Channel的ChannelPipeline

  • isActive:如果Channel是活动的,则返回true。活动的意义可能依赖于底层的传输。例如一个Socket传输一旦链接到了远程节点便是活动的,而一个Datagram传输一点被打开便是活动的

  • localAddress:返回本地的SockerAddress

  • remoteAddress:返回远程的SockerAddress

  • write:将数据写到远程节点。这个数据将被传递给ChannelPipeline,并且排队知道它被冲刷

  • flush:将之前已写的数据冲刷到底层传输,如一个Socket

  • writeAndFlush:等同于调用write()并接着调用flush()

Netty的Channel实现是线程安全的,因此可以存储一个到Channel的引用,并且每当需要向远程节点写数据时,都可以使用它,即使当时很多线程都在使用它。

EventLoop

Channel、EventLoop、Thread以及EventLoopGroup的关系:

  1. 一个EventLoopGroup包含一个或者多个EventLoop

  2. 一个EventLoop在它的生命周期内只有一个Thread绑定

  3. 所有由EventLoop处理的IO事件都将在它专有的Thread上被处理(不是很理解,是说EventLoop绑定的特定线程池么,还是说EventLoop线程)

  4. 一个Channel在它的生命周期内只注册于一个EventLoop

  5. 一个EventLoop可能被分配给一个或多个Channel(这种表述方式容易让人迷惑)

在这种设计模式中,一个给定的Channel的IO操作都是由相同的Thread执行的,实际上消除了对同步的需要。

(我现在迷惑的是EventLoop上发现了IO事件,它是交给自己的线程池处理,还是由EventLoop线程处理,如果由EventLoop线程处理,如果任务阻塞了该怎么办,这时候用taskQueue么,如果不是由EventLoop线程处理,感觉和上面的描述有矛盾)