【问题标题】:Netty - fire ReadTimeoutHandler if multiple reads in channelNetty - 如果通道中有多个读取,则触发 ReadTimeoutHandler
【发布时间】:2016-09-05 00:15:43
【问题描述】:

我的 I/O 流程如下:

  1. 客户端向通道发送数据#1
  2. server(handler)根据客户端数据从数据库接收数据并发送给客户端
  3. 客户端将数据#2 发送到通道
  4. server(handler)根据客户端数据再次从数据库中接收数据并发送回客户端并关闭通道

如果第一次读取通道时间过长,ReadTimeoutHandler 会按预期触发异常。但是,如果第一次读取正常(= 足够快)并且第二次读取通道花费的时间太长,则不会抛出 TimeoutException 并且处理程序等待 5 分钟直到它关闭通道。似乎 ReadTimeoutHandler 仅适用于通道中的第一次读取。是否有可能让 ReadTimeoutHandler 在通道中进行多次读取?

使用的 Netty 版本:4.0.12

公共类 MyServer {

private static final class MyInitializer extends ChannelInitializer<SocketChannel> {

...

    @Override
    public void initChannel(SocketChannel channel) throws Exception {
        channel.pipeline().addLast(
                new ReadTimeoutHandler(5, TimeUnit.SECONDS),
                new MyHandler(server, serverConnection));
    }

...

}

}

公共类 MyHandler 扩展 SimpleChannelInboundHandler {

private static final Logger LOG = LoggerFactory.getLogger(MyHandler.class);

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    super.channelActive(ctx);
}

@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
    Message message = database.getMessage(msg);
    ChannelFuture operation = ctx.writeAndFlush(message) 

if (message.isEnd()) operation.addListener(new CloseConverstationListener(ctx));
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    if (cause instanceof ReadTimeoutException) {
        LOG.error("ReadTimeoutException");
    } 
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    super.channelInactive(ctx);
}

private class CloseConverstationListener implements GenericFutureListener<ChannelFuture> {
    private final ChannelHandlerContext ctx;

    private CloseConverstationListener(ChannelHandlerContext ctx) {
        this.ctx = ctx;
    }

    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
        future.channel().close().sync();
    }
}

}

【问题讨论】:

  • 您确定发布了完整的管道吗?没有完成从字节到字符串的对话。

标签: java netty


【解决方案1】:

ReadTimeoutHandler 的行为是 - 如果在指定的持续时间内通道中没有发生读取,它将触发异常并关闭通道。这不是为了响应或处理读取的延迟。 在通道读取开始时,读取标志设置为真,当读取完成时设置为假。调度程序运行,它检查通道是否打开并且在指定的持续时间内没有读取,然后它会触发异常并关闭连接。

如果第一次读入频道时间过长,ReadTimeoutHandler 会按预期触发异常。

以上对我来说听起来不正确。 如果你想根据写响应的延迟来超时,你可以考虑 WriteTimeoutHandler。

【讨论】:

  • 感谢您的回答。我仍然认为 ReadTimeoutHandler 在我的情况下无法正常工作,或者我不明白它应该如何工作。它适用于通道中的第一次读取,以防它超时,但是当第二次(或第三次等)读取到来时,ReadTimeoutHandler 不会引发异常,例如当客户端断开连接并且不再有读取时。 ReadTimeoutHandler channelRead-method 被调用(再次),但它永远不会引发异常,因为 ReadTimeoutHandler 状态是在第一次读取 1(或 2?)之后,我理解正确,它的值应该是 0 调度任务再次被触发。跨度>
  • 如果客户端断开连接,则没有活动通道。当有一个活动通道并且在指定的持续时间内没有在通道上发生读取时,此处理程序将抛出异​​常并关闭通道。这是为了防止不必要的通道增长。 HTH
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-30
  • 2018-01-15
相关资源
最近更新 更多