我正在开发一个使用 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 中的错误?还有什么其他相关的,我可能错过了吗?