采用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

Logo

更多推荐