采用phantomjs driver执行任务时抛异常‘java.lang.RuntimeException: Unable to find a free port’。
首先查看linux 系统的端口范围:
less /proc/sys/net/ipv4/ip_local_port_range
或
sysctl net.ipv4.ip_local_port_range
得出结果是1024 65535
表示端口范围是1024 ~ 65535
经查看源码发现会自动获取可用端口:
原代码内指定端口范围:
public static final int HIGHEST_PORT = 65535; public static final int START_OF_USER_PORTS = 1024;
获取端口方法:
private static int createAcceptablePort() { synchronized (random) { final int FIRST_PORT; final int LAST_PORT; int freeAbove = HIGHEST_PORT - ephemeralRangeDetector.getHighestEphemeralPort(); int freeBelow = max(0, ephemeralRangeDetector.getLowestEphemeralPort() - START_OF_USER_PORTS); if (freeAbove > freeBelow) { FIRST_PORT = ephemeralRangeDetector.getHighestEphemeralPort(); LAST_PORT = 65535; } else { FIRST_PORT = 1024; LAST_PORT = ephemeralRangeDetector.getLowestEphemeralPort(); } if (FIRST_PORT == LAST_PORT) { return FIRST_PORT; } if (FIRST_PORT > LAST_PORT) { throw new UnsupportedOperationException("Could not find ephemeral port to use"); } final int randomInt = random.nextInt(); final int portWithoutOffset = Math.abs(randomInt % (LAST_PORT - FIRST_PORT + 1)); return portWithoutOffset + FIRST_PORT; } }
其中:
ephemeralRangeDetector.getHighestEphemeralPort() 获取的值是系统端口范围的最大值,此处即65535
ephemeralRangeDetector.getLowestEphemeralPort() 获取的值是系统端口范围的最小值,此处即1024
所以按照逻辑得出FIRST_PORT =1024,LAST_PORT=1024,最终返回1024。 即只能用1024这个端口。当其他phantomjs线程在运行的时候即占用了该端口,导致无法使用新的phantomjs进程。解决办法:把系统的端口范围最小值调到大于1024, 最大值不能变。如 将端口范围调到1124 ~ 65535:sysctl -w net.ipv4.ip_local_port_range="1124 65535"
或echo 1124 65535 > /proc/sys/net/ipv4/ip_local_port_range