【Netty】生命周期 详解

shadowLogo

前言:

在我们学习 Spring 系列 时,我们发现,Spring 之所以一直立于 Java届开发基本上必选框架,其中一个 主要原因 就是:

Spring使用框架的用户 留有 很多 扩展点

在我们使用 Netty 时,会发现 Netty 给我们也留了很多 扩展点

那么,本篇博文中,本人就来讲解下 Netty扩展点 —— 生命周期


首先,本人来展示下 Netty生命周期 都有哪些 扩展点

包含 扩展点:

  • handlerAdded
    新建立的连接会按照初始化策略,把handler添加到该channel的pipeline里面,也就是channel.pipeline.addLast(new LifeCycleInBoundHandler)执行完成后的回调
  • channelRegistered
    当该连接分配到具体的worker线程后,该回调会被调用
  • channelActive
    channel的准备工作已经完成,所有的pipeline添加完成,并分配到具体的线上上,说明该channel准备就绪,可以使用了
  • channelRead
    客户端向服务端发来数据,每次都会回调此方法,表示有数据可读
  • channelReadComplete
    服务端每次读完一次完整的数据之后,回调该方法,表示数据读取完毕
  • channelInactive
    当连接断开时,该回调会被调用,说明这时候底层的TCP连接已经被断开了
  • channelUnRegistered
    对应channelRegistered,当连接关闭后,释放绑定的workder线程
  • handlerRemoved
    对应handlerAdded,将handler从该channel的pipeline移除后的回调方法

那么,这些 扩展点调用顺序 是怎么样的呢?

调用顺序:

Netty生命周期


现在,本人来通过 一个小Demo 来 证明 下 上文讲解的正确性:

使用展示:

首先是 服务端

服务端:

package edu.youzg.demo.lifecycle;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @Author: Youzg
 * @CreateTime: 2021-05-07 15:25
 * @Description: 带你深究Java的本质!
 */
public class NettyServerDemo {

    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new LifeCycleInBoundHandler());
                        }
                    });

            System.out.println("Netty Server start...");
            ChannelFuture channelFuture = bootstrap.bind(9000).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    static class LifeCycleInBoundHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelRegistered(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("channelRegistered: 客户端channel注册到NioEventLoop");
        }

        @Override
        public void channelUnregistered(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("channelUnregistered: 客户端channel 取消和 NioEventLoop 的绑定");
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("channelActive: channel准备就绪");
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("channelInactive: channel被关闭");
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg)
                throws Exception {
            System.out.println("channelRead: channel中有可读的数据");
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("channelReadComplete: channel读数据完成");
        }

        @Override
        public void handlerAdded(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("handlerAdded: handler被添加到channel的pipeline");
        }

        @Override
        public void handlerRemoved(ChannelHandlerContext ctx)
                throws Exception {
            System.out.println("handlerRemoved: handler从channel的pipeline中移除");
        }

    }

}

接下来是 客户端

客户端:

package edu.youzg.demo.lifecycle;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.StandardCharsets;

/**
 * @Author: Youzg
 * @CreateTime: 2021-05-07 15:25
 * @Description: 带你深究Java的本质!
 */
public class NettyClientDemo {

    public static void main(String[] args) {
        NioEventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new ClientHandler());
                        }
                    });

            System.out.println("Netty Client start...");
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }

    static class ClientHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush(Unpooled.copiedBuffer("Youzg is a good man!".getBytes(StandardCharsets.UTF_8)));
        }
    }
    
}

最后,本人来展示下 运行结果

运行结果:

1
2
我们可以看到:

生命周期Handler调用顺序,和本人上文所讲一致!


那么,至此,Netty生命周期,就讲解完毕了!

在之后的博文中,本人也会通过讲解 源码,来讲解下 Netty 内部的 实现逻辑
结束

posted @ 2021-05-07 16:29  在下右转,有何贵干  阅读(871)  评论(0编辑  收藏  举报