对于如何将Netty不同的部分组织起来,成为一个可以实际运行应用程序,Bootstrap就是我们需要的,引导一个应用程序进行配置,并使其运行起来

Bootstrap类

引导类的层次结构包含一个抽象的父类和两个具体的引导子类

图片

不同的引导类分别作为服务器和客户端的引导,支持不同的应用程序的功能

服务器使用一个父Channel来接受客户端的连接,创建子Channel用于通信

客户端只需要一个单独的,没有父Channel的Channel进行所有网络通信

首先是Bootstrap类开始

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {

子类型B方便返回运行时实例的引用

子类的声明如下

public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {

引导Bootstrap中有很多API,继承了AbstractBootstrap类

图片 图片

我们进行客户端的引导过程

Bootstrap类为客户端和应用程序创建Channel

图片

图片

图片

Channel和EventLoopGroup的兼容性

对于NIO和OIO传输两者来说,都有不同的EventLoopGroup和Channel的实现

图片

如果将NIO和OIO的EventLoop和Channel混合起来了的话,会可能出现问题,尤其是出现IllegalStateException

图片

创建了一个Bootstrap的实例,绑定了NIO的EventLoopGroup的实现,

Channel指定的却是OIO的Channel实现类

会导致IllegalStateException,混用了不兼容的传输

在引导过程中,调用bind()或者 connect()方法之前,调用以下方法来设置所需的组件

group()

channel或者channelFactory()

handler()

不然就导致IllegalStateException

服务器端的引导是我们需要主要深究的方向

serverBootstrap的api如下

图片

从上面的API列表中可以看出,Server端的引导器比起客户端的多了不少方法,比如childHandler

ChildAttr childOption,因为Server端的引导,是由一个ServerChannel负责创建子Channel

子Channel代表了已经被接受的连接,因此,负责引导ServerChannel的ServerBootstrap提供了这些方法

下面就是ServerBootstrap的bind()方法在调用的时候创建了一个ServerChannel,并且这个ServerChannel管理了多个子Channel

图片

整体的ServerBootstrap的引导流程如下

图片

假如,我们需要处理一个客户端的请求,然后把自己作为客户端,将这个请求转发出去,那么需要在已经接受的子Channel中引导一个客户端Channel

通过已经被接受的子Channel的EventLoop传递给Bootstrap的group()方法来共享这个EventLoop,这就避免了额外的线程创建

图片

ServerChannel创建的Channel再去引导一个Bootstrap,并且利用一个EventLoop来进行线程的共享,避免了上下文的切换

图片

图片

上面说了,尽可能使用EventLoop来避免线程上下文切换带来的开销

如何在引导的过程中添加多个ChannelHandler呢?

如果我们需要多个Handler利用一个ChannelPipeline进行串联的话,我们如何做呢?

Netty是有一个特殊的ChannelInboundHandlerAdapter子类

图片

定义了如下的方法

图片

在传入Bootstrap之后,一旦Channel注册到了EventLoop之后,会调用这个InitChannel方法,在这个方法中,我们可以利用传入的Channel获得对应的ChannelPipeline

然后添加对应的Handler

基本代码如下

图片

图片

设置Netty的ChannelOption和属性

每个Channel创建时候都手动配置会导致相当的麻烦,所以可以在引导的时候配置一个ChannelOption,然后自动为所有的Channel进行加上这个配置

ChannelOption 包括底层连接的详情,如keep-alive和缓冲区设置

Netty甚至提供了AttributeMap抽象 有Channel和引导类提供的集合

和AttributeKey, 插入和获取属性值的泛型类

使用这个工具,将Channel和其他类型的数据绑定

比如,将用户Id和Channel绑定

具体的使用ChannelOption的方式如下

图片

图片

对于基于无连接的协议的SocketChannel,Netty提供了各类DatagramChannel的实现

图片

对于引导启动的关闭

需要我们在JVM退出的时候处理好一切

我们需要关闭EventLoopGroup,处理任何挂起的事件和任务,然后释放所有的线程,这就是调用EventLoopGroup.shutdownGracefully()方法的作用,返回调用一个Future,这说明这个方法是异步的,需要我们阻塞等待响应,或者注册一个监听器在关闭完成时候获得通知

发表评论

邮箱地址不会被公开。 必填项已用*标注