我正在使用Netty 4.0.25编写一个网络服务器。我正在用一个客户端程序测试它,它也是用Netty编写的。
=>客户端在循环中连续地向服务器发送数据约2次,如下所示;
try {
for(int i=0;i<noOfSubmit;i++){
ByteBuf submit_packet= createSubmitsmPacket(components, PduConstants.SUBMIT_SM);
f = ctx.channel().writeAndFlush(submit_packet);
try {
f.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("SENDING DATA "+count++);
submit_packet = null;
}
} catch (Exception e) {
e.printStackTrace();
} 在上面的代码中,如果删除"f.await()“行,那么就不能通过重新初始化下一个数据包数据来重用Bytebuf变量" submit_packet ",因为发送操作"writeAndFlush”是异步的,因此它可能仍然在使用submit_packet。如果我为for循环中的每次迭代使用一个新的submit_packet变量实例,我将不必要地创建许多对象并增加GC上的负载。
OTOH,如果我使用f.await()行,那么在发送大约70K数据包之后,我会继续得到BlockingOperationException。我认为这是因为底层TCP缓冲区可能已经满了。
我的问题如下: 1.得到这个BlockingOperationException是否正常?
为阻塞异常添加堆栈跟踪
io.netty.util.concurrent.BlockingOperationException: DefaultChannelPromise@4ba6b85d(uncancellable)
at io.netty.util.concurrent.DefaultPromise.checkDeadLock(DefaultPromise.java:390)
at io.netty.channel.DefaultChannelPromise.checkDeadLock(DefaultChannelPromise.java:157)
at io.netty.util.concurrent.DefaultPromise.await(DefaultPromise.java:251)
at io.netty.channel.DefaultChannelPromise.await(DefaultChannelPromise.java:129)
at io.netty.channel.DefaultChannelPromise.await(DefaultChannelPromise.java:28)
at com.comviva.mbs.msdpv6.ecp_smpp_tester.EcpSMPPTestEncoder.sentSubmitPacketsToCP(EcpSMPPTestEncoder.java:146)
at com.comviva.mbs.msdpv6.ecp_smpp_tester.EcpSMPPTestEncoder.unlimitLoop(EcpSMPPTestEncoder.java:137)
at com.comviva.mbs.msdpv6.ecp_smpp_tester.EcpSMPPTestEncoder.createPacket(EcpSMPPTestEncoder.java:92)
at com.comviva.mbs.msdpv6.ecp_smpp_tester.EcpSMPPTestEncoder.channelActive(EcpSMPPTestEncoder.java:57)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:208)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:194)
at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:758)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:258)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:288)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:722)发布于 2016-01-11 12:36:40
防止GC收集不必要对象的解决方案是使用基于池的ByteBufAllocator,例如PooledByteBufAllocator。这些分配器的优点是,使用过的对象返回到池中,而不是由gc收集,但是您需要确保在释放它们之后不要使用它们。
您可以在处理程序中使用它们,如下所示:
ByteBuf submit_packet = PooledByteBufAllocator.DEFAULT.buffer(initialCapacity, maxCapacity);
createSubmitsmPacket(submit_packet, components, PduConstants.SUBMIT_SM);
f = ctx.channel().writeAndFlush(submit_packet);其中,initialCapacity被返回的ByteBuf的初始容量替换,maxCapacity的容量也一样。
如果您需要对ByteBuf进行更多的控制,那么您应该创建一个新的PooledByteBufAllocator实例,并将参数传递给它的构造函数,说明该做什么。
https://stackoverflow.com/questions/29161129
复制相似问题