Netty案例实战分析之核心链路源码

DBC 1.1K 0

一、深入剖析EventLoop和EventLoopGroup线程模型

    • 高性能RPC框架的3个要素:IO模型、数据协议、线程模型
    • EventLoop好比一个线程,1个EventLoop可以服务多个Channel,1个Channel只有一个EventLoop。可以创建多个 EventLoop 来优化资源利用,也就是EventLoopGroup
    • EventLoopGroup 负责分配 EventLoop 到新创建的 Channel,里面包含多个EventLoop

二、Netty启动引导类Bootstrap模块

group :设置线程组模型,Reactor线程模型对比EventLoopGroup

单线程

    /**
     * 启动流程
     */
    public void run() throws InterruptedException {

        //配置服务端线程组  两个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

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

            System.out.println("Echo 服务器启动ing");

            //绑定端口,同步等待成功
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            //等待服务端监听端口关闭
            channelFuture.channel().closeFuture().sync();
        } finally {

            //优雅退出,释放线程池
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }


    }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
serverBootstrap.group(bossGroup)

多线程

    /**
     * 启动流程
     */
    public void run() throws InterruptedException {

        //配置服务端线程组  两个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

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

            System.out.println("Echo 服务器启动ing");

            //绑定端口,同步等待成功
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            //等待服务端监听端口关闭
            channelFuture.channel().closeFuture().sync();
        } finally {

            //优雅退出,释放线程池
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }


    }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
serverBootstrap.group(bossGroup,workGroup)

主从线程

    /**
     * 启动流程
     */
    public void run() throws InterruptedException {

        //配置服务端线程组  两个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

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

            System.out.println("Echo 服务器启动ing");

            //绑定端口,同步等待成功
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            //等待服务端监听端口关闭
            channelFuture.channel().closeFuture().sync();
        } finally {

            //优雅退出,释放线程池
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }


    }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup();
serverBootstrap.group(bossGroup, workGroup)

参考

点我前往

channel:设置channel通道类型NioServerSocketChannel、OioServerSocketChannel

option

  • option: 作用于每个新建立的channel,设置TCP连接中的一些参数,如下
    • ChannelOption.SO_BACKLOG: 存放已完成三次握手的请求的等待队列的最大长度;
    • Linux服务器TCP连接底层知识:
      • syn queue:半连接队列,洪水攻击,tcp_max_syn_backlog
      • accept queue:全连接队列, net.core.somaxconn
    • 系统默认的somaxconn参数要足够大 ,如果backlog比somaxconn大,则会优先用后者 点我前往
    • ChannelOption.TCP_NODELAY: 为了解决Nagle的算法问题,默认是false, 要求高实时性,有数据时马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数,就设置为false,会累积一定大小后再发送
    • 知识拓展:
  • childOption: 作用于被accept之后的连接
  • childHandler: 用于对每个通道里面的数据处理

客户端启动引导类Bootstrap

  • remoteAddress: 服务端地址
  • handler:和服务端通信的处理器

三、Netty核心组件Channel模块

  • 什么是Channel: 客户端和服务端建立的一个连接通道
  • 什么是ChannelHandler: 负责Channel的逻辑处理
  • 什么是ChannelPipeline: 负责管理ChannelHandler的有序容器
  • 他们是什么关系:
    • 一个Channel包含一个ChannelPipeline,所有ChannelHandler都会顺序加入到ChannelPipeline中 创建Channel时会自动创建一个ChannelPipeline,每个Channel都有一个管理它的pipeline,这关联是永久性的
  • Channel当状态出现变化,就会触发对应的事件
    • 状态:
      • channelRegistered: channel注册到一个EventLoop
      • channelActive: 变为活跃状态(连接到了远程主机),可以接受和发送数据
      • channelInactive: channel处于非活跃状态,没有连接到远程主机
      • channelUnregistered: channel已经创建,但是未注册到一个EventLoop里面,也就是没有和Selector绑定

四、ChannelHandler和ChannelPipeline模块

  • 方法:
    • handlerAdded : 当 ChannelHandler 添加到 ChannelPipeline 调用
    • handlerRemoved : 当 ChannelHandler 从 ChannelPipeline 移除时调用
    • exceptionCaught : 执行抛出异常时调用
  • ChannelHandler下主要是两个子接口
    • ChannelInboundHandler:(入站)
      • 处理输入数据和Channel状态类型改变
      • 适配器 ChannelInboundHandlerAdapter(适配器设计模式)
      • 常用的:SimpleChannelInboundHandler
    • ChannelOutboundHandler:(出站)
      • 处理输出数据,适配器 ChannelOutboundHandlerAdapter
  • ChannelPipeline: 好比厂里的流水线一样,可以在上面添加多个ChannelHanler,也可看成是一串 ChannelHandler 实例,拦截穿过 Channel 的输入输出 event, ChannelPipeline 实现了拦截器的一种高级形式,使得用户可以对事件的处理以及ChannelHanler之间交互获得完全的控制权

发表评论 取消回复
表情 图片 链接 代码

分享