其他分享
首页 > 其他分享> > Netty学习(二):Netty的核心组件

Netty学习(二):Netty的核心组件

作者:互联网

学习Netty有一个很大的苦难点就是关于Netty有一大堆的专有名词,如果不懂这些专有名词的意思,就很难读懂源码和理解Netty的流程。

一、Netty的核心组件(慢慢补充)

一.ByteBuf(缓冲区,Netty 的数据容器)

buffer中文名又叫缓冲区,是”在数据传输时,在内存里开辟的一块临时保存数据的区域”。它其实是一种化同步为异步的机制,可以解决数据传输的速率不对等以及不稳定的问题。
根据这个定义,我们可以知道,在涉及IO的地方,基本都会有Buffer存在,最常见的就是JAVA IO操作文件的读取和写入,outputStream.write()只将内容写入了buffer,必须调用outputStream.flush(),才能保证数据写入生效。

二.Channel(通道,连接)

Channel 是 Java NIO 的一个基本构造。
它代表一个到实体( 如一个硬件设备、一个文件、一个网络套接字或者一个能够执行一个或者多个不同的I/O操作的程序组件) 的开放连接,如读操作和写操作

目前,可以把 Channel 看作是传入(入站)或者传出(出站)数据的载体。因此,它可以被打开或者被关闭,连接或者断开连接。

1、ServerSocketChannel (客户端和引导服务器信道)

连接客户端和引导服务器的信道

2、SocketChannel(引导服务器和工作服务器信道)

客户端和工作服务器的信道,将引导服务器将客户转交给工作服务器。

3、ChannelHandler(消息处理器)

ChannelHandler 是消息的具体处理器,主要负责处理客户端/服务端接收和发送的数据。

4、ChannelPipeline( 消息处理器的容器)

ChannelPipeline是ChannelHandler 的容器,将不同的消息处理器放入其中。

三.EventLoop 和EventLoopGroup (事件轮询器和事件轮询器群,控制流、多线程处理、并发 )

当一个连接到达时,Netty 就会注册一个 Channel,然后从 EventLoopGroup 中分配一个 EventLoop 绑定到这个 Channel 上,在该 Channel 的整个生命周期中都是有这个绑定的 EventLoop 来服务的。

四.ServerBootstrap(引导服务器)

Netty采用了Reactor模型,引导服务器为Netty服务器的入口。

二、Netty服务端代码示例

我用比较通俗的方式来描述一下Netty服务端代码流程,因为存在异步方法,所以代码的执行并不完全是我们看到的顺序,我由上到下进行介绍。

以海底捞举例,我以从门口到吃饭过程来描述Netty服务器所需要的配置信息。

1、门店就是引导服务器(ServerBootstrap),没有门店,也不需要服务员和顾客。

2、门店需要服务员,海底捞的服务员分为门迎服务员(bossGroup)和桌台服务员(workerGroup),比如在这里我们配置了1个门迎和8个桌台,这个数字不是乱写的,首先门迎不需要很多,桌台服务员也和店里的桌子个数有关,对于服务器来讲,就是和CPU的核数有关,一般设置为CPU核数*2+1。

3、将服务员带到门店( bootstrap.group(bossGroup, workerGroup) //设置两个线程组)

4、门迎服务员可能什么都不懂,我们需要对他进行培训,让他知道如何和新来的顾客打交道(.channel(NioServerSocketChannel.class) //使用NioSocketChannel作为服务器的通道),以及配置他最多可去迎接多少个顾客(.option(ChannelOption.SO_BACKLOG, 128) //设置线程队列等待连接个数),以及要不要及多久和顾客打一次招呼( .childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态)

5、门迎比较傻,他还不认识里面的桌台服务员,要把桌台服务员介绍给他。(.childHandler(new ChannelInitializer() {//设置workerGroup的eventLoop对应的管道处理器)

6、桌台的服务员也很傻,需要对他培训,教他怎么调油碗,教他怎么倒水,让顾客点菜,这里的单个操作就是(ChannelHandler,消息处理器),整个培训就叫做(ChannelPipeline)

socketChannel.pipeline().addLast(new NettyServerHandler());//这里只有一个,实际的应用场景会有很多。

7、门店不光需要去工商局注册,还需要实际的地址,也就需要绑定占用一个端口。我们可以一边培训服务员,一边装修门店,这就叫做异步方法,但是如果服务员培训好了,门店还没装修好,就必须进行同步,让服务员等门店装修好了才能上班。 ChannelFuture channelFuture = bootstrap.bind(6668).sync(); //绑定一个端口,并且同步,启动服务器

public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        //创建BossGroup和WorkerGroup
        //说明:
        //1. 创建两个线程组bossGroup和workerGroup
        //2. bossGroup只是处理链接请求,真正的和客户端业务处理,会交给workerGroup
        //3. 两个都是无限循环的
        //4. bossGroup和workerGroup含有子线程的(NioEventLoop)的个数,默认实际cup核数*2
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);
        try {
            /**
             * 创建服务器端的启动对象,配置参数
             */
            ServerBootstrap bootstrap = new ServerBootstrap();

            /**
             * 使用链式编程来进行设置
             */
            bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                    .channel(NioServerSocketChannel.class) //使用NioSocketChannel作为服务器的通道
                    .option(ChannelOption.SO_BACKLOG, 128) //设置线程队列等待连接个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {//设置workerGroup的eventLoop对应的管道处理器
                        //给pipeline设置处理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //可以使用集合管理SocketChannel,在推送消息时,可以将业务加入到各个chanel对应的NIOEventLoop的taskQueue或ScheduleTaskQueue
                            log.info("客户端SocketChannel hashCode={}", socketChannel.hashCode());
                            socketChannel.pipeline().addLast(new NettyServerHandler());
                        }
                    });

            log.info("服务器 is ready...");
            //涉及netty异步模型
            ChannelFuture channelFuture = bootstrap.bind(6668).sync(); //绑定一个端口,并且同步,启动服务器

            //给channelFuture注册监听器,监控我们关系的事件
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if(future.isSuccess()) {
                        log.info("监听端口6668成功");
                    }else {
                        log.info("监听端口失败");
                    }
                }
            });

            log.info("判断是否是异步操作");

            //对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

标签:Netty,服务员,new,workerGroup,bossGroup,核心,组件,服务器
来源: https://blog.csdn.net/qq_38173650/article/details/117293972