【问题标题】:Is it possible to catch netty exception in Camel?是否可以在 Camel 中捕获 netty 异常?
【发布时间】:2018-10-16 22:51:51
【问题描述】:

在我看来,netty 有自己的异常处理程序,它们不会将异常(即 IOException)传播回骆驼路线。有什么方法可以知道客户端已断开连接?

【问题讨论】:

    标签: java apache-camel


    【解决方案1】:

    回答我自己的问题。 我的问题是释放客户端,这些客户端将永远等待从 netty 获得某种响应,主要是在处理管道期间远程主机关闭连接的情况下。

    需要做的是向管道添加一个自定义处理程序,该处理程序应该扩展ChannelDuplexHandler并覆盖connect并写入methodsSimpleChannelInboundHandler并覆盖channelInactive。我用ChannelDuplexHandler

    public class ExceptionHandler extends ChannelDuplexHandler {
    
    private final NettyProducer producer;
    
    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress,
                        ChannelPromise promise)
            throws Exception {
        ctx.connect(remoteAddress, localAddress, promise)
                .addListener((future -> {
                    if (!future.isSuccess()) {
                        // no need to do anything here, camel will manage it on its own
                    }
                }));
    }
    
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        ctx.write(msg, promise).addListener(future -> {
            if (!future.isSuccess()) {
                reportStatusBackToCamel(ctx);
            }
        });
    }
    
    private void reportStatusBackToCamel(ChannelHandlerContext ctx) {
        NettyCamelState nettyCamelState = producer.getCorrelationManager().getState(ctx, ctx.channel(),
                new IOException());
        Exchange exchange = nettyCamelState.getExchange();
        AsyncCallback callback = nettyCamelState.getCallback();
        exchange.setException(new RuntimeException("Client disconnected"));
        callback.done(false);
        }
    }
    

    如果是SimpleChannelInboundHandler,只需将交换处理放入channelInactive 方法中。

    initChannel 中的ClientInitializerFactory 中,将此处理程序添加到管道:

     pipeline.addLast(new ExceptionHandler(producer));
    

    producer 在应用程序启动时提供给您。如果您像我一样需要额外的 spring 注入 bean,那么您最终会在您的工厂类中拥有几个构造函数,一个 @Autowired(带有您注入的字段)调用另一个设置额外的生产者字段。

    【讨论】:

    • 感谢您回答自己的问题。我遇到了同样的问题,Netty 自己处理异常,而不是传播回我的 Camel 路由(在相同的设置中与 mina 一起工作)。我已经尝试过您的方法,但是我无法从写入中获取 if (!future.isSuccess()) 以在断开连接时触发。设置是 route 1 -> route 2 (netty producer) -> route 3 (throw new CamelExchangeException),其中 route 1 和 2 在同一个 RouteBuilder 中,并且 route 3 正在模拟一个主机,其中在某些条件下会引发异常用于测试目的。对此有什么想法吗?谢谢!
    猜你喜欢
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    相关资源
    最近更新 更多