Netty 实现高并发通讯原理理解

1.前言

        最近写了很多关于Netty应用级别的文章,针对为什么选择Netty来实现高并发通讯,Netty实现高并发通讯的原理是什么?今天有时间把我对Netty的一些理解做个简单的说明,如有不对欢迎指正与探讨。

2.Netty工作原理

         上图是我对Netty实现高并发通讯工作机制的一个简单理解,当我们的智能终端接入到网关程序后,首先是由一个线程池进行进行绑定操作,我们叫它(parentGroup),绑定之后将后续的事情交给另外一个线程池进行后续的处理,我们叫它(childGroup)

parentGroup 负责处理客户端的TCP连接请求,如果服务端只有一个端口需要监听,建议将其线程数设置为1,相当于Reactor模型中的Acceptor线程池。

childGroup 负责I/O的读写操作,通过 ServerBootstrap 的 group 方法进行设置,用于后续产生的 Channel 绑定,相当于Reactor模型中的NIO线程池。可以不设置线程数,默认为当前服务器的处理器核心数*2。

        这里会有人疑问,并没有提及Netty如何实现高并发通讯机制,接触过Netty的都清楚,Netty是NIO框架,使用到Selector组件进行实现多路复用,其实通过上图workGroup一个EventLoop管理多个Channel,其实就是采用的Selector来实现的。

        另外Netty采用的是零拷贝ByteBuf,可以减少内存复制,从而减少GC,提升效率,并且其相应的read与write操作也是非常好用的。

3.实现代码解析

package com.gateway.xxxx.netty;

import com.gateway.xxxx.constants.Constant;
import com.gateway.xxxx.netty.codec.FrameDecoder;
import com.gateway.xxxx.netty.codec.ProtocolDecoder;
import com.gateway.xxxx.netty.codec.ProtocolEncoder;
import com.gateway.xxxx.netty.handler.BusinessHandler;
import com.gateway.xxxx.netty.handler.LoginHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * TCP服务类
 * @author Mr.xxx
 * @date 20210101
 */
@Slf4j
public class TcpServer extends Thread{
    private int port;

    private EventLoopGroup bossGroup;

    private EventLoopGroup workerGroup;

    private ServerBootstrap serverBootstrap = new ServerBootstrap();
    //这里引入计数器的意思是如果开启多个TCP服务,可以通过计数器来判断是否所有的tcp服务都已经正常启动
    private CountDownLatch countDownLatch;

    public TcpServer(int port, CountDownLatch countDownLatch) {
        this.port = port;
        this.countDownLatch = countDownLatch;

        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();
        //启动一个EventExecutorGroup来处理比较耗时的业务
        final EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(Math.max(threadPoolSize, Runtime.getRuntime().availableProcessors() * 2));
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childHandler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new IdleStateHandler(HcIotConstant.READER_IDLE_TIME, 0, 0, TimeUnit.SECONDS));
                        ch.pipeline().addLast(new FrameDecoder());
                        //添加一个接收数据包预处理业务,和统一的指令下发封装业务
                        ch.pipeline().addLast(ProtocolDecoder.INSTANCE, new ProtocolEncoder());
                        //添加一个登录鉴权
                        ch.pipeline().addLast(LoginHandler.INSTANCE);
                        //添加一个业务处理(业务处理比较耗时,这里可以使用EventExecutorGroup来处理比较耗时的业务)
                        ch.pipeline().addLast(executorGroup,BusinessHandler.INSTANCE);
                    }
                });
    }

    @Override
    public void run() {
        bind();
    }

    /**
     * 绑定端口启动服务
     */
    private void bind() {
        serverBootstrap.bind(port).addListener(future -> {
            if (future.isSuccess()) {
                log.info("{} TCP服务器启动,端口:{}", protocolType, port);
                countDownLatch.countDown();
            } else {
                log.error("{} TCP服务器启动失败,端口:{}", protocolType, port, future.cause());
                System.exit(-1);
            }
        });
    }

    /**
     * 关闭服务端
     */
    public void shutdown() {
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
        log.info("{} TCP服务器关闭,端口:{}", protocolType, port);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_17486399/article/details/121770192
今日推荐