ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-05-28 09:05:28  阅读:201  来源: 互联网

标签:Netty 服务员 new workerGroup bossGroup 核心 组件 服务器


学习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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有