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的关系:
-
一个EventLoopGroup包含一个或者多个EventLoop
-
一个EventLoop在它的生命周期内只有一个Thread绑定
-
所有由EventLoop处理的IO事件都将在它专有的Thread上被处理(不是很理解,是说EventLoop绑定的特定线程池么,还是说EventLoop线程)
-
一个Channel在它的生命周期内只注册于一个EventLoop
-
一个EventLoop可能被分配给一个或多个Channel(这种表述方式容易让人迷惑)
在这种设计模式中,一个给定的Channel的IO操作都是由相同的Thread执行的,实际上消除了对同步的需要。
(我现在迷惑的是EventLoop上发现了IO事件,它是交给自己的线程池处理,还是由EventLoop线程处理,如果由EventLoop线程处理,如果任务阻塞了该怎么办,这时候用taskQueue么,如果不是由EventLoop线程处理,感觉和上面的描述有矛盾)