Netty - 一个exceptionCaught()事件被触发,它到达了管道的尾部

时间:2016-11-01 23:20:41

标签: java exception client-server netty

我在日志中收到了这个警告:

Nov 02, 2016 12:07:20 AM io.netty.channel.DefaultChannelPipeline onUnhandledInboundException
WARNUNG: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.util.concurrent.TimeoutException

这是我的ChannelHandlers:

@Override
public void initChannel(SocketChannel ch) throws Exception {
    ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
    ch.pipeline().addLast(new TimeoutHandler(TIME_OUT_SECONDS));
    ch.pipeline().addLast(new ServerCommunicationHandler(messageHandler));
}

如果最近15秒没有读取,我的TimeoutHandler会抛出TimeoutException。 在我的最后一个处理程序ServerCommunicationHandler中,我已经覆盖了exeptionCaught函数:

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    ctx.close();
}

因此,如果我理解正确,我不会将异常重新抛出到管道的末尾,因为我的上一个处理程序正确处理了异常,不是吗?

为什么我会收到此警告?

我使用Netty 4.1.6.Final

2 个答案:

答案 0 :(得分:1)

这可能是由于TimeoutHandler在关闭通道后抛出TimeoutException。这可能发生,因为一旦一个频道关闭,所有的ChannelHandler都将被删除(未注册),但ChannelHandlerContext仍然有一个对该管道的引用,所以如果你关闭一个频道,然后在ctx上发起一个事件就赢了是拦截事件的任何处理者。

我能够通过编写一个简单/破坏的TimeoutHandler重新创建您看到的错误:

@RequiredArgsConstructor
private static class TimeoutHandler extends ChannelInboundHandlerAdapter {
    private final int timeoutSeconds;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ctx.executor().schedule(
                // This exception can still be fired once the channel is closed and all handlers removed
                () -> ctx.fireExceptionCaught(new TimeoutException()), 
                timeoutSeconds, TimeUnit.SECONDS);
        super.channelRegistered(ctx);
    }
}

您是否考虑过使用Netty ReadTimeoutHandler而不是自己编写?

如果您真的想自己编写,请确保在频道处于非活动状态时取消定时器。你可以看到IdleStateHandler does this的方式。

答案 1 :(得分:0)

也许这是由于接收到的数据不完整而引发的异常? 我的项目最近也遇到了这个问题,因为接收到的数据代码是GBK,并且我使用的是utf8,因此在拦截相应位置的数据时,我将下标超出范围并抛出了该错误。

screenshot of error message which is neither English nor printable with ISO-8859 charset