0
votes

I have a Camel application that communicates with a remote server over TCP using the netty component. The server has a tendency to hang and so I want to be able to add a configurable timeout on a request so that if a response isn't returned in X amount of time, I'd get an exception.

The mina component has this capability in the timeout parameter, but the netty component doesn't appear to have a corresponding option.

I tried accomplishing this with a ReadTimeoutHandler and that came close... but not quite. It starts with creating a HashedWheelTimer when initializing the CamelContext:

HashedWheelTimer timer = new HashedWheelTimer();
JndiRegistry jndi = new JndiRegistry();
jndi.bind("MyClientPipelineFactory", new MyClientPipelineFactory(timer));

And then add it to my pipeline:

public class MyClientPipelineFactory extends ClientPipelineFactory
{
  private final Timer timer;

  public MyClientPipelineFactory(Timer timer) {
    this.timer = timer;
  }

  public ChannelPipeline getPipeline(NettyProducer producer) throws Exception
  {
    ChannelPipeline p = pipeline();
    p.addLast("timeout", new ReadTimeoutHandler(timer, 30));
    // more stuff
    return p;
  }
}

Finally, I catch any exceptions in my routes configuration:

onException(ReadTimeoutException.class)
   .handled(true)
   .process(new Processor() {
      public void process(Exchange exchange) throws Exception {
         Exception exception = (Exception) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
         throw new ApplicationException("Connection timed out", exception);
      }
   });

This almost works. Unfortunately, it is channel specific and not request specific. So as long as I'm communicating with the server, I'm fine. But 30 seconds after I am done, I get a ReadTimeoutException thrown. The problem is that it's looking for any activity on the wire and not the request/response pairs that I care about.

Am I missing something here? Is there an inherent way of doing request timeouts using Camel+Netty or is there some way to make the ReadTimeoutException work?

(Camel 2.9.2/Netty 3.3.1)

2

2 Answers

1
votes

I'm not familiar with Camel but a quick look at the Mina and Netty components suggests that the required functionality is a feature of the Mina component, not Mina, and it's missing from the Netty component. In camel trunk, the Mina producer has a code path for when sync is true, whereas the Netty producer doesn't appear to have similar functionality. It might be worth taking the question to the camel mailing lists.

A possible workaround is to create a custom Netty handler that is request / response aware, so you have a handler in your pipeline that starts a timer when the request is sent, and cancels the timer when the response is received.

0
votes

I wonder if we could add some kind of support for this. To trigger timeout on the given exchange request/reply pair.

I assume ReadTimeoutHandler is from Netty? I guess we could peak in the code and see if we can only let it trigger if there is "in-flight" exchanges.

A trick is also how to handle if a reply come back later, and a timeout was already triggered. Then Camel would need to deal with this to cancel processing the reply. I am not sure if that is so easy to do.