【问题标题】:Jetty IOException: Too many open filesJetty IOException:打开的文件太多
【发布时间】:2011-06-12 15:38:09
【问题描述】:

我在一个网站上运行 Jetty,每秒大约 100 个请求,前面有 nginx。我刚刚在日志中注意到,在进行部署并启动 Jetty 几分钟后,有一段时间它正在发送垃圾邮件:

java.io.IOException: Too many open files
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:163)
    at org.mortbay.jetty.nio.SelectChannelConnector$1.acceptChannel(SelectChannelConnector.java:75)
    at org.mortbay.io.nio.SelectorManager$SelectSet.doSelect(SelectorManager.java:673)
    at org.mortbay.io.nio.SelectorManager.doSelect(SelectorManager.java:192)
    at org.mortbay.jetty.nio.SelectChannelConnector.accept(SelectChannelConnector.java:124)
    at org.mortbay.jetty.AbstractConnector$Acceptor.run(AbstractConnector.java:708)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

一两分钟。 我做了一个“lsof -u jetty”,看到了数百行:

java    15892 jetty 1020u  IPv6          298105434        0t0       TCP 192.168.1.100:http-alt->192.168.1.100:60839 (ESTABLISHED)
java    15892 jetty 1021u  IPv6          298105438        0t0       TCP 192.168.1.100:http-alt->192.168.1.100:60841 (ESTABLISHED)
java    15892 jetty 1022u  IPv6          298105441        0t0       TCP 192.168.1.100:http-alt->192.168.1.100:60842 (ESTABLISHED)
java    15892 jetty 1023u  IPv6          298105443        0t0       TCP 192.168.1.100:http-alt->192.168.1.100:60843 (ESTABLISHED)

其中 192.168.1.100 是服务器内部 IP。

如您所见,这使打开文件的数量达到默认最大值 1024。我可以增加这个数量,但我想知道为什么会发生这种情况?是在Jetty的nio socket acceptor中,所以这是连接请求风暴造成的吗?

【问题讨论】:

  • 每个套接字都是一个文件,因此每个连接都有一个文件(描述符),即使它正在等待。请求通常会做什么,需要多长时间?码头上有 100 个请求/秒,查询本地数据库服务器需要 2 秒/请求,您已经有 400 个“文件”。
  • 我的大多数请求只需要几毫秒,尽管当应用程序第一次启动时它们可能需要几秒钟,我认为这就是发生的情况。垃圾收集器也偶尔会“stop the world”暂停,这会导致所有请求在短时间内堆积起来,从而导致这种情况间歇性发生。稍后我将不得不调整 GC,同时我只是增加了限制。
  • 我不时在Tomcat6中得到类似的东西,最初以为是操作系统扔了它的玩具。也只是增加了限制作为临时解决方案。

标签: java jetty nio ioexception


【解决方案1】:

虽然 Jetty 中可能存在错误,但我认为更可能的解释是您的打开文件 ulimit 太低。通常 1024 默认值对于适度使用的 Web 服务器来说是不够的。

对此进行测试的一个好方法是使用 apache bench 来模拟您看到的入站流量。在远程主机上运行此程序将生成 1000 个请求,每个请求超过 10 个并发连接。

ab -c 10 -n 1000 [http://]hostname[:port]/path

现在使用 netstat 计算 Web 服务器上的套接字...

netstat -a | grep -c 192.168.1.100

希望您会发现,您的套接字将稳定在某个值不会显着大于 1024(我的是 16384)。

要确保的另一件好事是在您的业务逻辑中正确关闭连接。

netstat -a | grep -c CLOSE_WAIT

如果您看到这个数字在您的应用程序的生命周期中持续增长,您可能会错过一些对 Connection.close() 的调用。

【讨论】:

  • 此外,如果 Full GC 确实占用了太多时间,请查看 java 的 ConcurrentMarkSweep 收集器。
【解决方案2】:

我通过将 Spring Boot 升级到最新的 2.4.1 解决了由 Spring Boot 应用程序(版本 2.2.8 或 2.3.1)中的 bug 引起的类似问题

【讨论】:

    猜你喜欢
    • 2011-01-03
    • 2011-05-16
    • 2016-07-18
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多