当前位置: 首页 > 知识库问答 >
问题:

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

江琦
2023-03-14

我在netty server应用程序中面临资源问题。

[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]
lsof -p 5604 | grep socket | wc -l

无法看到与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();

更新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

所以收盘前有60秒的差距(正如ReadTimeouthHandler所预期的那样)

经过更多的分析,我有了这样的印象,即使与客户端正常断开连接,打开的文件数量也会增加!而且,在这种情况下没有CLOSE()...

共有1个答案

姜旭
2023-03-14

也许这与这个棘手的问题有关https://github.com/netty/netty/issues/1731

这是预期的行为,是无法改变的。JVM正在发出信号,表示它无法接受该通道--因此无法启动连接,也无法发送响应。客户端将看到连接失败。如果您有一个负载平衡器,它应该对备用主机重试,或者代表您的应用程序返回503。

 类似资料:
  • 已经问过类似的问题,但是删掉了,既然以为我修好了,但是我错了。 我在生产中为我的一个web项目使用Play framework。有时播放不呈现主页面或不返回一些静态内容文件。 最初应用程序运行良好,它必须工作5-7天,我可以看到这个问题。很难重现,它发生了15次中的1次,我不得不删除缓存数据和重新加载页面。(按下FF中的CRTL-F5)。问题可以在不同机器和操作系统的大多数浏览器中重现。最初,我认

  • 我正试图用Netty开发以下用例: 客户端连接到上的中间服务器(端口 8900)。 客户端将具有配置的处理器请求发送到另一台计算机。 第 3 台计算机根据配置启动处理器。 处理器连接到根据配置中标识的端口(例如端口 8901)启动处理器的同一服务器。 服务器现在根据两者之间共享的匹配唯一哈希绑定客户端和处理器。 将为每个新的客户端连接创建新处理器。 客户端连接不是问题。我有一个处理这些请求的客户端

  • 问题内容: 我敢肯定这是一个简单的问题,但是我不知道socket.io文档在哪里,而http://labs.learnboost.com/socket.io/上的文档并没有真正的帮助。 假设我有一个socket.io http服务器,并写了一个网站来连接它。 我如何为服务器提供保护,以使未经授权的人(未通过网站连接的人)被阻止/丢弃/禁止。 如何在服务器端结束套接字连接?所以如果我有 如何结束套接

  • 我正在开发一个非常简单的Java客户机/服务器系统(只是为了让我的脚沾满套接字)。由于某种原因,我一直收到“套接字已关闭”错误。。。这是我的密码。。 服务器文件 客户端文件 我在客户端的第41行得到了错误,然后在第46行得到了NullPointerException。。 提前感谢您的帮助。我只是想在这里学习。

  • 问题内容: 我有服务器和客户端。我的服务器接受所有连接并返回到客户端字符串。但是当我尝试发送更多行时,它崩溃了 这是我的服务器代码: 这是我的客户代码: 问题答案: 来自in中的javadoc: 关闭返回将关闭关联的套接字。 另外,关闭(和所有其他打印机/写入器)也将关闭其基础流。因此,您可以通过关闭(in ),然后尝试写入已关闭的套接字来关闭您的套接字。 要解决此问题,请不要关闭。垃圾收集将为您

  • 我正在编写一个简单的客户端/服务器套接字程序,其中客户端与服务器连接并通信,然后它们向服务器发送退出消息,然后服务器关闭连接。代码如下所示。 服务器.py client.py 我想要的是万一服务器通过ctrl-c或任何其他方式退出,我希望关闭所有客户端套接字,并将msg发送给客户端,他们也应该在其上关闭套接字。 我在下面除部分之外的部分做了一些工作,但由于某些原因,客户端没有收到服务器发送的消息。