首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Netty BlockingOperationException

Netty BlockingOperationException
EN

Stack Overflow用户
提问于 2015-03-20 07:01:30
回答 1查看 1.3K关注 0票数 0

我正在使用Netty 4.0.25编写一个网络服务器。我正在用一个客户端程序测试它,它也是用Netty编写的。

=>客户端在循环中连续地向服务器发送数据约2次,如下所示;

代码语言:javascript
复制
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是否正常?

  1. 忽略BlockingOperationException并继续重试发送操作是否安全。在这种情况下,是否可以等待大约半秒钟,然后重试,或者我可以立即重试。什么是最佳做法?
  2. 在服务器端,我必须向客户端数据包发送响应。在成功地向每个传入数据包发送响应后,我必须在服务器上执行一些业务逻辑。为此,我在服务器上使用f.await(),如果成功,则执行业务逻辑。

为阻塞异常添加堆栈跟踪

代码语言:javascript
复制
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)
EN

回答 1

Stack Overflow用户

发布于 2016-01-11 12:36:40

防止GC收集不必要对象的解决方案是使用基于池的ByteBufAllocator,例如PooledByteBufAllocator。这些分配器的优点是,使用过的对象返回到池中,而不是由gc收集,但是您需要确保在释放它们之后不要使用它们。

您可以在处理程序中使用它们,如下所示:

代码语言:javascript
复制
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实例,并将参数传递给它的构造函数,说明该做什么。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29161129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档