1

我正在开发一个使用 Netty 发送/接收 RTP 流量的应用程序。在负载测试期间,我们注意到我们的单个工作线程在尝试等待 Netty 关闭通道时遇到了死锁。

语境:

  • 所有 RTP 端点之间有一个共享NioEventLoopGroup(=> UDP 套接字)
  • 当仍有流量接收时,通道可能会关闭
  • 通道的关闭肯定发生在来自专用工作线程的 Netty 线程之外
  • Netty 版本是 4.1.65

引导代码:

EventLoopGroup eventLoopGroup = RtpEventLoopGroup.acquireEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(eventLoopGroup);
b.channel(NioDatagramChannel.class);
b.option(ChannelOption.SO_BROADCAST, true);
b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
b.handler(new ChannelInitializer<DatagramChannel>() {
    @Override
    public void initChannel(final DatagramChannel ch) {
        ch.pipeline().addLast(new RtpInboundChannelHandler(rtpReceiver));
    }
});
Channel channel = b.bind(localAddress).syncUninterruptibly().channel();

关机代码:

channel.disconnect().syncUninterruptibly();
channel.close().syncUninterruptibly();
RtpEventLoopGroup.releaseEventLoopGroup();

卡住的工作线程的线程转储(NettyDatagramSocket:107指向channel.close()方法):

Worker Thread
  at java.lang.Object.wait(J)V (Native Method)
  at java.lang.Object.wait()V (Object.java:328)
  at io.netty.util.concurrent.DefaultPromise.awaitUninterruptibly()Lio/netty/util/concurrent/Promise; (DefaultPromise.java:275)
  at io.netty.channel.DefaultChannelPromise.awaitUninterruptibly()Lio/netty/channel/ChannelPromise; (DefaultChannelPromise.java:137)
  at io.netty.channel.DefaultChannelPromise.awaitUninterruptibly()Lio/netty/util/concurrent/Promise; (DefaultChannelPromise.java:30)
  at io.netty.util.concurrent.DefaultPromise.syncUninterruptibly()Lio/netty/util/concurrent/Promise; (DefaultPromise.java:411)
  at io.netty.channel.DefaultChannelPromise.syncUninterruptibly()Lio/netty/channel/ChannelPromise; (DefaultChannelPromise.java:125)
  at io.netty.channel.DefaultChannelPromise.syncUninterruptibly()Lio/netty/channel/ChannelFuture; (DefaultChannelPromise.java:30)
  at mypackage.NettyDatagramSocket.close()V (NettyDatagramSocket.java:107)

NIO EventLoopGroup线程有8个,都是[alive, runnable]

  • 一些当前正在处理接收到的数据包
  • 他们似乎都没有处理通道关闭
  • 一些显示以下线程堆栈:
NIO EventLoopGroup-1
  at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(JI[I[I[IJJ)I (Native Method)
  at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll()I (WindowsSelectorImpl.java:357)
  at sun.nio.ch.WindowsSelectorImpl.doSelect(Ljava/util/function/Consumer;J)I (WindowsSelectorImpl.java:182)
  at sun.nio.ch.SelectorImpl.lockAndDoSelect(Ljava/util/function/Consumer;J)I (SelectorImpl.java:124)
  at sun.nio.ch.SelectorImpl.select()I (SelectorImpl.java:141)
  at io.netty.channel.nio.SelectedSelectionKeySetSelector.select()I (SelectedSelectionKeySetSelector.java:68)
  at io.netty.channel.nio.NioEventLoop.select(J)I (NioEventLoop.java:810)
  at io.netty.channel.nio.NioEventLoop.run()V (NioEventLoop.java:457)
  at io.netty.util.concurrent.SingleThreadEventExecutor$4.run()V (SingleThreadEventExecutor.java:989)
  at io.netty.util.internal.ThreadExecutorMap$2.run()V (ThreadExecutorMap.java:74)
  at java.lang.Thread.run()V (Thread.java:829)

这看起来像是我的应用程序中的错误还是我可以假设这是 Netty 中的错误?还有什么其他相关的,我可能错过了吗?

4

0 回答 0