Netty任务队列中的Task有三种典型使用场景

时光毁灭记忆、已成空白 提交于 2020-02-12 12:20:06
每个NioEventLoop里都有一个selector与TaskQueue,当我们在进行一些耗时的操作的时候,会产生阻塞,这时候我们就可以用到TaskQueue
具体实现有三种:

1.用户程序自定义的普通任务:在自定义的handler的channelRead方法中:

        // 比如这里我们有一个非常耗时的业务,异步执行,提交该channel 对应的NioEventLoop的TaskQueue中
        // 解决方案1:
        ctx.channel().eventLoop().execute(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(10000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端1",CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    System.out.println("发生异常");
                }
            }
        });

2.用户自定义定时任务,该任务提交到scheduleTaskQueue中

        ctx.channel().eventLoop().schedule(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(5000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端1",CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    System.out.println("发生异常");
                }
            }
        },5, TimeUnit.SECONDS);

3.非当前reactor线程调用的各种方法,在设置参数的时候通过hashcode,例如在推送系统的业务线程里面,根据用户的标识,找到对应的channel引用,然后调用Write类方法向该用户推送消息,就会进入到这种场景。最终的Write会提交到任务队列中后被异步消费

serverBootstrap.group(bossGroup,workGroup)
                    // 使用NioServerSocketChannel作为服务器的通道实现
                    .channel(NioServerSocketChannel.class)
                    // 设置线程队列得到连接个数
                    .option(ChannelOption.SO_BACKLOG,128)
                    // 设置保持活动连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    // 给我们的workGroup的EventLoop对应的管道设置处理器
                    // 创建一个通道测试对象
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        // 给pipeline设置处理区
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 可以使用一个集合来管理 socketChannel ,
                            // 在推送消息时,可以将业务加入到各个channel对应的NIOEventLoop的taskQueue或者scheduleTaskQueue中
                            System.out.println("客户socketChannel hashcode="+socketChannel.hashCode());
                            socketChannel.pipeline().addLast(new JymNettyServerHandler());
                        }
                    });
方案再说明

1.netty抽象出两组线程池,BossGroup专门负责客户端连接,WorkerGroup专门负责网络读写操作
2.NioEventLoop表示一个不断循环执行处理任务的线程,每个NioEventLoop都有一个selector,用于监听绑定在其上的socket网络通道
3.NioEventLoop内部采用串行化设计,从纤细的读写,解码,处理,编码,发送,始终由IO线程的NioEventLoop负责

对象之前的关系

NioEventGroup下包含多个NioEventLoop
每个NioEventLoop中包含有一个Selector,一个taskQueue
每个NioEventLoop的selector上可以注册监听多个NioChannel
每个NioChannel只会绑定在唯一的NioEventLoop上
每个NioChannel都绑定有一个自己的Channel与Pipeline

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!