如何检测Apache Camel中的网络断开连接?

时间:2017-01-30 16:11:00

标签: logging error-handling apache-camel

我需要在客户端与Apache Camel连接断开连接时进行记录。如何检测netty-tcp断开连接?

    from("{{uri.client.address}}")

2 个答案:

答案 0 :(得分:1)

记录单个客户端断开连接有点复杂,但我会尝试分享我必须做的事情。

您需要使用自己的类扩展SimpleChannelInboundHandler并添加所需的方法。有关示例课程,请参见此处:

https://github.com/apache/camel/blob/master/components/camel-netty4/src/main/java/org/apache/camel/component/netty4/handlers/ServerChannelHandler.java

在那里查看我已更改为包含客户端断开连接的主要方法是:

 @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    //command to send when there is a disconnect from client side
    String command = "clientDisconnect";
    if (LOG.isTraceEnabled()) {
      LOG.trace("Channel closed: {}", ctx.channel());
    }
    LOG.info("Channel has disconnected: affects ", uniqueClientId);
    //create Exchange and let the consumer process it
    final Exchange exchange = consumer.getEndpoint().createExchange(ctx, command);
    //create inOnly as there is no client waiting for a response
    exchange.setPattern(ExchangePattern.InOnly);
    // set the exchange charset property for converting
    if (consumer.getConfiguration().getCharsetName() != null) {
      exchange.setProperty(Exchange.CHARSET_NAME, IOHelper.normalizeCharset(consumer.getConfiguration().getCharsetName()));
    }
    // we want to handle the UoW
    consumer.createUoW(exchange);
    //set the uniqueClientId
    beforeProcess(exchange, ctx, command);
    processAsynchronously(exchange, ctx, command);
    // to keep track of open sockets
    consumer.getNettyServerBootstrapFactory().removeChannel(ctx.channel());
    super.channelInactive(ctx);
}

如果频道已连接,请注意我记录的部分。

如果要为主路径中的不同客户端执行不同的操作,也可以记录不同客户端的IP地址。这应该对你有帮助。

编辑: 扩展该类后,调用扩展类TCPServerHandler。然后,您需要创建一个TCPServerHandlerFactory来引用上一个类并设置您的编码器/解码器。这个类看起来像这样:

public class TCPServerInitializerFactory extends ServerInitializerFactory  {
  private NettyConsumer consumer;

  public TCPServerInitializerFactory(NettyConsumer consumer) {
    this.consumer = consumer;
  }
  @Override
  protected void initChannel(Channel channel) throws Exception {
    ChannelPipeline pipeline = channel.pipeline();
    pipeline.addLast("string-encoder", new StringEncoder(CharsetUtil.UTF_8));
    pipeline.addLast("string-decoder", new StringDecoder(CharsetUtil.UTF_8));
    **pipeline.addLast("handler", new TCPServerHandler(consumer));**
  }

  @Override
  public ServerInitializerFactory createPipelineFactory(NettyConsumer nettyConsumer) {
    return new TCPServerInitializerFactory(nettyConsumer);
  }
}

标有**的行是您创建TCPServerHandler类的地方。

然后回到路线类中的驼峰,您需要将工厂添加到您的注册表中,如下所示:

TCPServerInitializerFactory serverFactory = new TCPServerInitializerFactory(null);
    final CamelContext camelContext = getContext();
    final org.apache.camel.impl.SimpleRegistry registry = new org.apache.camel.impl.SimpleRegistry();
    final org.apache.camel.impl.CompositeRegistry compositeRegistry = new org.apache.camel.impl.CompositeRegistry();
    compositeRegistry.addRegistry(camelContext.getRegistry());
    compositeRegistry.addRegistry(registry);
    ((org.apache.camel.impl.DefaultCamelContext) camelContext).setRegistry(compositeRegistry);
registry.put("spf", serverFactory);

然后这样说:

from("netty4:tcp://0.0.0.0:3000?serverInitializerFactory=#spf&sync=true")...

现在您可能想知道,所有这些都要注册断开连接的日志。这是因为能够区分客户端断开连接并实际获取Netty代码所需的客户端IP。您可以在交易中保存一些价值,然后在您的路线中做一些事情。

答案 1 :(得分:-1)

使用ErrorHandler,例如LoggingErrorHandler:

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // use logging error handler
        errorHandler(loggingErrorHandler("com.mycompany.foo"));

        // here is our regular route
        from("{{uri.client.address}}").to("mock:out");
    }
};