【问题标题】:Netty 4 io.netty.channel.PartialFlushException after writeNetty 4 io.netty.channel.PartialFlushException 写入后
【发布时间】:2013-02-27 01:56:33
【问题描述】:

第二次 .write 在我的代码中的新通道上,写入操作的ChannelFuture.isSuccess 为假,ChannelFuture.causeio.netty.channel.PartialFlushException: 0 out of 1 message(s) flushed。我不知道应该做些什么来避免这种情况,以及在哪里寻找更深层次的根本原因。

ChannelFuture.cause.getStackTraceString 是:

io.netty.channel.ChannelOutboundMessageHandlerAdapter.flush(ChannelOutboundMessageHandlerAdapter.java:118) io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:237) io.netty.channel.DefaultChannelHandlerContext.invokeFlush0(DefaultChannelHandlerContext.java:1308) io.netty.channel.DefaultChannelHandlerContext.write0(DefaultChannelHandlerContext.java:1445) io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:1412) io.netty.channel.DefaultChannelHandlerContext.write(DefaultChannelHandlerContext.java:1034) io.netty.channel.DefaultChannelPipeline.write(DefaultChannelPipeline.java:959) io.netty.channel.AbstractChannel.write(AbstractChannel.java:246) pipe.Broker$writer$.write(Broker.scala:72) pipe.Broker$httpClientHandler.messageReceived(Broker.scala:57) pipe.Broker$httpClientHandler.messageReceived(Broker.scala:52) io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:104) io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:951) io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:926) io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:904) io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:466) io.netty.handler.codec.ByteToMessageDecoder.inboundBufferUpdated(ByteToMessageDecoder.java:69) io.netty.channel.ChannelInboundByteHandlerAdapter.inboundBufferUpdated(ChannelInboundByteHandlerAdapter.java:51) io.netty.channel.CombinedChannelDuplexHandler.inboundBufferUpdated(CombinedChannelDuplexHandler.java:194) io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:951) io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:926) io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:904) io.netty.channel.DefaultChannelPipeline.fireInboundBufferUpdated(DefaultChannelPipeline.java:909) io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:115) io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:401) io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:365) io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:302) io.netty.channel.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:110) java.lang.Thread.run(未知来源)

通道上的第一个 .write 运行良好(isSuccess 为真,并且确实写入的消息完美地到达并在其目的地解析)。但是第二个 .write 始终如前所述失败。

第二个 .write 是从我重写的 ChannelInboundMessageHandlerAdapter.messageReceived 方法中发出的,一旦它收到远程对等方收到第一个 .write 的确认。

我执行实际写入的代码(这是 Scala)是:

 request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"+msg)
              var writeFuture = channel.write(request).addListener(new ChannelFutureListener(){
                  def operationComplete(channelFuture: ChannelFuture){
                    if (channelFuture.isSuccess)
                        println("write finished successfully")
                    else 
                        println ("write failed: " + channelFuture.cause + "\n" + channelFuture.cause.getStackTraceString)
                  }
              })

可能是什么问题,应该如何追踪?

【问题讨论】:

  • 请注意,接受的答案建议通过使用更详细的 printStackTrace 方法或在未来使用 .cause.getCause 来查看失败的更“根本”原因。它满足了追踪问题的需要(尽管尚未找到根本问题的解决方案 - 除非在 stackoverflow.com/questions/15097966/… 回答)

标签: netty


【解决方案1】:

PartialFlushException 包含刷新失败的实际原因。您可以使用 Java 提供的Exception.getCause() 方法获取它:

PartialFlushException e = ...;
e.getCause(); // This will return the exception you raised.

要获取异常的完整信息,而不是打印异常,您必须调用printStackTrace()

future.cause.printStackTrace()

有关链式异常的更多信息,请参阅this tutorial

【讨论】:

  • 谢谢。我的代码目前正在频道未来上使用 .cause 来获取原因文本。这似乎返回了 PartialFlushException 的原因文本“已刷新 1 条消息中的 0 条”。我对如何将其解释为根本原因一无所知。我能错过什么?顺便说一句,尝试将写入操作包装在 try 块中并不会在 catch 块中捕获异常,这可能是由于写入的异步性质。所以我只是假设 .cause 出现在频道未来是获取异常的方式,实际上它是带有我刚才提到的原因文本的 PartialFlushException。
  • 问题是,我很难以任何可行的方式解释文本。
  • PartialFlushException.getCause() 将返回另一个作为根本原因的异常。
  • 谢谢,使用 channelFuture.cause.getCause 显然确实更深一层,原因显示为“意外消息类型:DefaultHttpRequest”。鉴于管道纯粹是一个 HttpRequestEncoder,尚不确定为什么该类型的对象无效/预期!但这已经是一个标题不同的主题的问题了……我要结束这个了。如果您想在这里评论为什么 Http 管道上不需要 HttpRequestEncoder ,请不要拖延;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多