关于Netty中的channel.eventLoop.taskQueue

关于Netty中的channel.eventLoop.taskQueue正确用法

近日,看netty源码时发现一个问题,关于现在百度上大部分关于NioEventLoop(实际是SingleThreadEventExecutor)中的taskQueue的用法不是很正确,大部分博客都说taskQueue适合用来执行一些比较耗时的task,其实这并不正确,这是会阻塞NIO中的事件的

下面这部分代码来自netty4.1.x源码(NioEventLoop中的run()方法)
            if (ioRatio == 100) {
                try {
                    if (strategy > 0) {
                        processSelectedKeys();//处理NIO事件
                    }
                } finally {
                    // Ensure we always run tasks.
                    ranTasks = runAllTasks();//处理taskQueue或者scheduleTaskQueue中的task
                }
            } else if (strategy > 0) {
                final long ioStartTime = System.nanoTime();
                try {
                    processSelectedKeys();
                } finally {
                    // Ensure we always run tasks.//处理NIO事件
                    final long ioTime = System.nanoTime() - ioStartTime;
                    ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);//处理taskQueue或者scheduleTaskQueue中的task
                }
            } else {
                ranTasks = runAllTasks(0); // //处理taskQueue或者scheduleTaskQueue中的task
            }

你会发现,当taskQueue中的任务阻塞,其对应的EventLoop就会阻塞,导致该EventLoop不能处理NIO事件,我们的worker可能会处理几百个socketChannel,要是把阻塞任务放在bossGroup的EventLoop的taskQueue中,更是灾难性的。

实例

ServerHandler:
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
    ctx.executor().execute(() -> {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    ByteBuf buf = (ByteBuf)msg;
    System.out.println(buf.toString(CharsetUtil.UTF_8) + " " + System.currentTimeMillis());
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    ctx.writeAndFlush(Unpooled.copiedBuffer("hello, I'm server".getBytes(CharsetUtil.UTF_8)));
}
clientHandler
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
    String messsage = "hello, I'm client";
    ByteBuf buf = Unpooled.directBuffer(256);
    buf.writeBytes(messsage.getBytes());
    for (int i = 0; i < 50; i++){
        ReferenceCountUtil.retain(buf);
        ctx.writeAndFlush(buf);
    }
}
结果

hello, I’m client 1607617679658

hello, I’m client*49 1607617689658

你会发现俩条结果之间刚好相差了task sleep的时间,所以得出结论,taskQueue是会阻塞我们的EventLoop线程,导致我们不能即时处理NIO事件,所以,不应该在taskQueue中放置耗时太长的任务

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值