【问题标题】:java.net.BindException: Cannot assign requested address when opening too many connectionsjava.net.BindException:打开太多连接时无法分配请求的地址
【发布时间】:2015-08-07 11:17:15
【问题描述】:

我正在运行以下代码,它只是在无限循环中连接和关闭套接字:

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;

public class Main {
    public static void main(String[] args) throws Exception {
        Thread.sleep(1000);
        InetAddress localhost = InetAddress.getByName("127.0.0.1");
        InetSocketAddress localhostRpcbind = new InetSocketAddress(localhost, 111);
        SelectorProvider selectorProvider = SelectorProvider.provider();
        long iterations = 0;
        while (true) {
            try {
                SocketChannel socketChannel = selectorProvider.openSocketChannel();
                socketChannel.connect(localhostRpcbind);
                socketChannel.finishConnect();
                socketChannel.close();
                iterations ++;
            } catch (Exception e) {
                System.err.println("after " + iterations + " iterations");
                e.printStackTrace(System.err);
                throw e;
            }
        }
    }
}

端口 111 是 rpcbind 的端口(它已在我的机器上启动并运行)。 在第一次运行代码时,我会得到类似:

after 28239 iterations
java.net.BindException: Cannot assign requested address
    at sun.nio.ch.Net.connect0(Native Method)
    at sun.nio.ch.Net.connect(Net.java:458)
    at sun.nio.ch.Net.connect(Net.java:450)
    at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648)
    at Main.main(Main.java:16)

后续运行将立即失败(0 次迭代),直到一段时间后我再次获得第一个结果(~26-28k 次迭代然后失败)。

发生了什么事,我怎样才能让这个连接/断开循环无限期地正常运行?

我在 linux x64 (fedora 22) 上运行。

注意:是的,我知道代码是无用的,什么也不做,这是我正在尝试调查的更大问题的 SSCCE。

更新 - 我的机器上似乎遇到了临时端口耗尽:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768   61000

所以我有大约 28k 临时端口用于连接,这与我的错误相符

【问题讨论】:

  • 我猜这个问题与 Unix/Linux 比 Java 更相关。我建议添加这些标签。
  • 几年前我也遇到过类似的问题。与文件描述符的最大数量和套接字停留时间有关。

标签: java linux


【解决方案1】:

在绑定到大约 28K 个不同的端口后,系统已用完用于绑定套接字的临时端口。

这个问题的原因是为了打开一个 TCP 连接,操作系统分配了一个临时端口(用于源端口)。它将套接字绑定到分配的端口。 TCP连接关闭后,连接处于TIME_WAIT状态,通常为2分钟,由于历史原因(https://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed_new.svg),从我的角度来看,这个时间在当今大多数系统中都可以减少......其他讨论。

作为一种解决方案,您可以使用 sysctl 减少此超时:

将 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait 的值更改为像 1 这样的低数字,情况会有所改善。但是,如果您的应用程序足够快,可以在 1 秒内消耗约 28K 端口,您仍然会看到此异常。

您可以调整的其他 TCP 参数: 增加临时端口的范围:net.ipv4.ip_local_port_range net.ipv4.tcp_tw_reuse net.ipv4.tcp_tw_recycle

看:http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.htmlhttp://www.lognormal.com/blog/2012/09/27/linux-tcpip-tuning/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多