出站 ChannelHandler 的捕获所有异常处理

oli*_*ren 5 java asynchronous exception netty

在 Netty 中,您有入站和出站处理程序的概念。只需在管道末尾(尾部)添加通道处理程序并实现覆盖即可实现捕获所有入站异常处理程序exceptionCaught。如果未沿途处理,沿入站管道发生的异常将沿着处理程序传播,直到遇到最后一个处理程序。

传出处理程序并没有完全相反的情况。相反(根据 Netty in Action,第 94 页),您需要向通道添加一个侦听器 Future或者向传递Promise到.writeHandler

由于我不确定在哪里插入前者,我想我会选择后者,所以我做了以下操作ChannelOutboundHandler


    /**
     * Catch and log errors happening in the outgoing direction
     *
     * @see <p>p94 in "Netty In Action"</p>
     */
    private ChannelOutboundHandlerAdapter createOutgoingErrorHandler() {
        return new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
                logger.info("howdy! (never gets this far)");

                final ChannelFutureListener channelFutureListener = future -> {
                    if (!future.isSuccess()) {
                        future.cause().printStackTrace();
                        // ctx.writeAndFlush(serverErrorJSON("an error!"));
                        future.channel().writeAndFlush(serverErrorJSON("an error!"));
                        future.channel().close();
                    }
                };
                promise.addListener(channelFutureListener);
                ctx.write(msg, promise);
            }
        };
Run Code Online (Sandbox Code Playgroud)

这被添加到管道的头部:

    @Override
    public void addHandlersToPipeline(final ChannelPipeline pipeline) {
        pipeline.addLast(
                createOutgoingErrorHandler(),
                new HttpLoggerHandler(), // an error in this `write` should go "up"
                authHandlerFactory.get(),
                // etc

Run Code Online (Sandbox Code Playgroud)

问题是,write如果我在HttpLoggerHandler.write().

我该如何做这个工作?任何传出处理程序中的错误都应该“冒泡”到附加到头部的错误。

需要注意的重要一点是,我不仅仅是想关闭通道,我想将错误消息写回客户端(如 中所示serverErrorJSON('...')。在我尝试调整处理程序的顺序期间(也尝试了一些东西)从这个答案),我已经激活了监听器,但我无法写任何东西。如果我ctx.write()在监听器中使用,似乎我进入了一个循环,而使用future.channel().write...没有做任何事情。

Nor*_*rer 0

基本上你所做的是正确的......唯一不正确的是处理程序的顺序。您的ChannelOutboundHandlerAdapter桅杆将“作为最后一个出站处理程序”放置在管道中。这意味着它应该是这样的:

pipeline.addLast(
        new HttpLoggerHandler(),
        createOutgoingErrorHandler(),
        authHandlerFactory.get());
Run Code Online (Sandbox Code Playgroud)

原因是出站事件从管道的尾部流向头部,而入站事件从头部流向尾部。