Netty Comet异步请求超时

时间:2012-01-15 22:14:44

标签: java concurrency netty

我正在尝试使用Jboss Netty创建长轮询Comet。

如何配置超过30秒的时间?文件后面:

@Override
    public ChannelPipeline getPipeline() throws Exception {
    ChannelPipeline pipeline = Channels.pipeline();
     pipeline.addLast("decoder", new HttpRequestDecoder());
     pipeline.addLast("encoder", new HttpResponseEncoder());
     pipeline.addLast("handler", new HTTPRequestHandler());
     Timer timer = new HashedWheelTimer();
     pipeline.addLast("timeout", new IdleStateHandler(timer, 30, 30, 0));
    return pipeline; 

但它不起作用,我的请求将永远存在。怎么解决这个问题?

这是否意味着我需要实现Callable<T>,然后使用timeout参数调用Future.get并在TimeOutException发生时终止请求?那我应该使用Future<ChannelFuture>吗?

还有其他办法吗?

代码:

FutureExecutor executor = FutureExecutor.getInstance();

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        HttpRequest request = (HttpRequest) e.getMessage();
    ChannelFuture channelFuture = null;
        Callable<ChannelFuture> myRunnable = new MyCallable(e);
        Future<ChannelFuture> future = executor.fireEvent(myRunnable);

    try{
        channelFuture = future.get(40,TimeUnit.SECONDS);
        }catch (TimeoutException ex) {

        channelFuture = e.getChannel(Response timeOutResponse);
               // handle the timeout
        } catch (InterruptedException ex) {
        channelFuture = e.getChannel(Response interaptedResponse);

        } catch (ExecutionException ex) {
            channelFuture = e.getChannel(Response errorResponse);
        } 
        finally{
            future.cancel(true);
            channelFuture.addListener(ChannelFutureListener.CLOSE);
        }

}

并且在Callable内部我只是监控BlockedQueue:

@Override
public ChannelFuture call() {
        final BlockingQueue<String> queue  =.....
        while (true){
        Message message = queue.take();
                ChannelBuffer partialresponse = ChannelBuffers.buffer(message.toJson());
         ChannelFuture future = e.getChannel().write(partialresponse);
        return future;
        }
}

1 个答案:

答案 0 :(得分:1)

首先,您应该在管道之间共享一个HashedWheelTimer实例,因为它将为每个实例创建一个线程。但现在你的问题..

如果使用IdleStateHandler,还需要实现IdleStateAwareHandler或IdleStateAwareChannelUpstreamHandler,它将对IdleStateHandler触发的IdleState事件作出反应。因此,如果您希望在频道空闲后断开频道,您可以在收到频道后调用频道上的频道。

另见:

http://netty.io/docs/stable/api/org/jboss/netty/handler/timeout/IdleStateAwareChannelUpstreamHandler.html

另一个解决方案是添加ReadTimeoutHandler,然后在exceptionCaught(..)方法中捕获它时对ReadTimeoutException采取行动。

请参阅: http://netty.io/docs/stable/api/org/jboss/netty/handler/timeout/ReadTimeoutHandler.html