引导

批注 2020-07-09 112728

Bootstrap

名称 描述
Bootstrap group(EventLoopGroup) 设置用于处理Channel所有事件的EventLoopGroup
Bootstrap channel(Class<? extends C>), Bootstrap channelFactory( ChannelFactory<? extends C>) channel()方法指定了Channel的实现类。如果该实现类没提供默认的构造函数,可以通过调用channelFactory()方法来指定一个工厂类,它将会被bind()方法调用
Bootstrap localAddress( SocketAddress) 指定Channel应该绑定到的本地地址。如果没有指定,则将由操作系统创建一个随机的地址。或者,也可以通过bind()或者connect()方法指定localAddress
Bootstrap option(ChannelOption<> option,T value) 设置ChannelOption,其将被应用到每个新创建的ChannelChannelConfig。这些选项将会通过bind()或者connect()方法设置到Channel,不管哪个先被调用。这个方法在Channel已经被创建后再调用将不会有任何的效果。支持的ChannelOption取决于使用的Channel类型。
Bootstrap attr(Attribute<> key, T value) 指定新创建的Channel的属性值。这些属性值是通过bind()或者connect()方法设置到Channel的,具体取决于谁最先被调用。这个方法在Channel被创建后将不会有任何的效果。
Bootstrap handler(ChannelHandler) 设置将被添加到ChannelPipeline以接收事件通知的ChannelHandler
Bootstrap clone() 创建一个当前Bootstrap的克隆,其具有和原始的Bootstrap相同的设置信息
Bootstrap remoteAddress(SocketAddress) 设置远程地址。或者,也可以通过connect()方法来指定它
ChannelFuture connect() 连接到远程节点并返回一个ChannelFuture,其将会在连接操作完成后接收到通知
ChannelFuture bind() 绑定Channel并返回一个ChannelFuture,其将会在绑定操作完成后接收到通知,在那之后必须调用Channel. connect()方法来建立连接
String host = "127.0.0.1";
int port = 1234;
EventLoopGroup workerGroup = new NioEventLoopGroup();

try {
    Bootstrap b = new Bootstrap();
    // 指定线程工作池
    b.group(workerGroup);
    // 指定实例化channel的方式
    b.channel(NioSocketChannel.class);
    // 连接参数
    b.option(ChannelOption.SO_KEEPALIVE, true);
    b.handler(new ChannelInitializer<SocketChannel>() {
        @Override
        public void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(new TimeClientHandler());
        }
    });

    // Start the client.
    ChannelFuture f = b.connect(host, port).sync(); // (5)

    // Wait until the connection is closed.
    f.channel().closeFuture().sync();
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    workerGroup.shutdownGracefully();
}

ServerBootStrap

名称 描述
group 设置ServerBootstrap要用的EventLoopGroup。这个EventLoopGroup将用于ServerChannel和被接受的子Channel的I/O处理
channel 设置将要被实例化的ServerChannel
channelFactory 如果不能通过默认的构造函数创建Channel,那么可以提供一个Channel- Factory
localAddress 指定ServerChannel应该绑定到的本地地址。如果没有指定,则将由操作系统使用一个随机地址。或者,可以通过bind()方法来指定该localAddress
option 指定要应用到新创建的ServerChannelChannelConfigChannel- Option。这些选项将会通过bind()方法设置到Channel。在bind()方法被调用之后,设置或者改变ChannelOption都不会有任何的效果。所支持的ChannelOption取决于所使用的Channel类型。参见正在使用的ChannelConfig的API文档
childOption 指定当子Channel被接受时,应用到子ChannelChannelConfigChannelOption。所支持的ChannelOption取决于所使用的Channel的类型。参见正在使用的ChannelConfig的API文档
attr 指定ServerChannel上的属性,属性将会通过bind()方法设置给Channel。在调用bind()方法之后改变它们将不会有任何的效果
childAttr 将属性设置给已经被接受的子Channel。接下来的调用将不会有任何的效果
handler 设置被添加到ServerChannelChannelPipeline中的ChannelHandler。更加常用的方法参见childHandler()
childHandler 设置将被添加到已被接受的子ChannelChannelPipeline中的Channel- Handlerhandler()方法和childHandler()方法之间的区别是:前者所添加的ChannelHandler由接受子ChannelServerChannel处理,而childHandler()方法所添加的ChannelHandler将由已被接受的子Channel处理,其代表一个绑定到远程节点的套接字
clone 克隆一个设置和原始的ServerBootstrap相同的ServerBootstrap
bind 绑定ServerChannel并且返回一个ChannelFuture,其将会在绑定操作完成后收到通知(带着成功或者失败的结果)

Netty 通过指定 EventLoopGroup 来决定使用哪一种 Reactor 模型

// 单线程模式:
EventLoopGroup eventGroup new NioEventLoopGroup(1);
// 非主从多线程:
EventLoopGroup eventGroup new NioEventLoopGroup();
// 主从多线程:
EventLoopGroup bossGroup new NioEventLoopGroup();
EventLoopGroup workerGroup new NioEventLoopGroup()
// 接收到来的连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 处理已建立连接的流量
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
    // 复制启动服务器
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
            // 使用 NioServerSocketChannel 将到来的连接实例化为Channel
            .channel(NioServerSocketChannel.class)
            // 指定处理器来处理 channel 与 channel 的事件
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new DiscardServerHandler());
                }
            })
            // 指定一些参数(针对到来的连接)
            .option(ChannelOption.SO_BACKLOG, 128)
            // 指定一些参数(针对channel)
            .childOption(ChannelOption.SO_KEEPALIVE, true);

    // Bind and start to accept incoming connections.
    ChannelFuture f = b.bind(port).sync();

    // Wait until the server socket is closed.
    // In this example, this does not happen, but you can do that to gracefully
    // shut down your server.
    f.channel().closeFuture().sync();
} finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
}

尽可能重用 EventLoop , 减少先创创建所带来的的开销

ChannelOption

bootstrap.option(ChannelOption.SO_KEEPALIVE,true)
  .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);

ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数,函数listen(int socketfd,int backlog)用来初始化服务端可连接队列,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小

Channeloption.SO_KEEPALIVE参数对应于套接字选项中的SO_KEEPALIVE,该参数用于设置TCP连接,当设置该选项以后,连接会测试链接的状态,这个选项用于可能长时间没有数据交流的连接。当设置该选项以后,如果在两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文

关闭

Future<?> future = group.shutdownGracefully();  ← --  shutdownGracefully()方法将释放所有的资源,并且关闭所有的当前正在使用中的Channel
// block until the group has shutdown
future.syncUninterruptibly();