Netty服务器不关闭/释放套接字

时间:2015-03-02 14:59:18

标签: java sockets netty

我在netty服务器应用程序中遇到资源问题。

[io.netty.channel.DefaultChannelPipeline] An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.: java.io.IOException: Too many open files
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) [rt.jar:1.7.0_60]
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241) [rt.jar:1.7.0_60]
    at io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(NioServerSocketChannel.java:135) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:69) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-all-4.0.25.Final.jar:4.0.25.Final]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_60]

作为一种解决方法,我使用ulimit -n增加了最大打开文件,但我仍然可以增加文件/套接字的数量:

lsof -p 5604 | grep socket | wc -l

现在已超过3000 ......

无法看到与netstat的任何打开或挂起的连接...

我使用ReadTimeoutHandler通过以下exceptionHandler代码关闭未使用的连接:

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  if (cause instanceof ReadTimeoutException) {
    logger.debug("Read timeout - close connection");
  } else {
    logger.info(cause.getMessage());
  }
  ctx.close();
}

服务器引导程序如下所示:

ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
    ch.pipeline().addLast(new ReadTimeoutHandler(60));
    ch.pipeline().addLast(new LoggingHandler(mySpec.getPortLookupKey().toLowerCase()));
    ch.pipeline().addLast(new RawMessageEncoder());
    ch.pipeline().addLast(new RawMessageDecoder());
    ch.pipeline().addLast(new RequestServerHandler(ctx.getWorkManager(), factory));
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);

ChannelFuture channelFuture = b.bind(port).sync();

我错过了什么吗?一旦连接关闭(由远程主机或超时处理程序),打开文件的数量是否会减少?

我需要更改什么来节省资源?

更新:我使用netty 4.0.25

更新2: 根据要求,我将记录处理程序移到ReadTimeouthandler前面,这里是日志。 客户端通常断开连接的情况:

09:41:39,755 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] REGISTERED
09:41:39,756 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] ACTIVE
09:41:39,810 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(1024B)
09:41:39,813 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(1024B)
09:41:39,814 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(150B)
09:41:40,854 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] WRITE(1385B)
09:41:40,855 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] FLUSH
09:41:40,861 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 :> /127.0.0.1:4300] INACTIVE
09:41:40,864 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 :> /127.0.0.1:4300] UNREGISTERED

客户端不断开连接的情况:

10:04:24,104 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] REGISTERED
10:04:24,107 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] ACTIVE
10:04:24,594 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(1024B)
10:04:24,597 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(1024B)
10:04:24,598 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(150B)
10:04:25,638 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] WRITE(1383B)
10:04:25,639 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] FLUSH
10:05:25,389 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] CLOSE()
10:05:25,390 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] CLOSE()
10:05:25,390 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] INACTIVE
10:05:25,394 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] UNREGISTERED

结束前有60s的差距(正如ReadTimeoutHandler预期的那样)

经过多次分析后,我的印象是,即使与客户端正常断开连接,打开文件的数量也会增加!此外,在那种情况下没有CLOSE()...

1 个答案:

答案 0 :(得分:1)

也许它与此网络问题https://github.com/netty/netty/issues/1731

有关
  

这是预期的行为,并且无法改变。该   JVM表示它无法接受该通道 - 因此   无法启动任何连接,也无法发送响应。客户端   会看到连接失败。如果你有负载均衡器,它应该   重试备用主机,或返回您的主机上的503   代表申请。

相关问题