繁体   English   中英

TIME_WAIT 连接过多,出现“无法分配请求的地址”

[英]Too many TIME_WAIT connections, getting "Cannot assign requested address"

我有一个小的 web 应用程序,它打开一个 TCP 套接字连接,发出命令,读取响应,然后关闭每个请求到特定 REST 端点的连接。

我已经开始使用 Apache JMeter 对端点进行负载测试,并注意到运行一段时间后,我开始看到诸如“无法分配请求的地址”之类的错误,打开此连接的代码是:

def lookup(word: String): Option[String] = {
 try {
  val socket = new Socket(InetAddress.getByName("localhost"), 2222)
  val out = new PrintStream(socket.getOutputStream)
  val reader = new BufferedReader(new InputStreamReader(socket.getInputStream, "utf8"))
  out.println("lookup " + word)
  out.flush()

  var curr = reader.readLine()
  var response = ""
  while (!curr.contains("SUCC") && !curr.contains("FAIL")) {
    response += curr + "\n"
    curr = reader.readLine()
  }
  socket.close()
  curr match {
    case code if code.contains(SUCCESS_CODE) => {
      Some(response)
    }
    case _ => None
  }
 }
 catch {
   case e: Exception => println("Got an exception "+ e.getMessage); None
 }
}

当我运行 netstat 时,我还看到了很多以下 TIME_WAIT 连接状态,这对我来说意味着我的临时空间中的端口用完了。

tcp6       0      0 localhost:54646         localhost:2222          TIME_WAIT  
tcp6       0      0 localhost:54638         localhost:2222          TIME_WAIT  
tcp6       0      0 localhost:54790         localhost:2222          TIME_WAIT  
tcp6       0      0 localhost:54882         localhost:2222          TIME_WAIT 

我想知道这个问题的最佳解决方案是什么。 我目前的想法是创建一个连接池,在该连接池中运行在端口2222上的该服务的连接可以被不同的 HTTP 请求重用,而不是每次都创建新请求。 这是解决问题并使应用程序规模更好的明智方法吗? 引入似乎有很多开销,并且肯定会使我的应用程序更加复杂。

是否有任何其他解决方案可以帮助扩展此应用程序并克服我没有看到的端口问题? 我的 web 应用程序正在 Ubuntu linux VM 中运行。

是的,创建连接池是一个很好的解决方案。 但是,更简单的解决方案是让服务器关闭连接,而不是客户端。 在这种情况下,服务器的套接字而不是客户端将最终处于TIME_WAIT状态,因此客户端不会耗尽端口。 在服务器端,处于TIME_WAIT状态的连接不会使服务器用完端口,因为它们都使用相同的本地端口。

要确保服务器关闭连接,您需要从套接字(在客户端上)读取,直到达到文件结束条件。 此时,可以安全地关闭客户端上的套接字,因为服务器已经关闭了它。 当然,您需要确保服务器关闭套接字,而不是等待新请求。

或者,如果您具有root访问权限,则可以调整一些sysctl选项:

  • net.ipv4.ip_local_port_range - 短暂端口的范围。 增加它以使更多端口可用于传出连接。
  • net.ipv4.tcp_tw_recycle - 在TIME_WAIT状态下更快地回收连接。
  • net.ipv4.tcp_tw_reuse - 在TIME_WAIT状态下启用连接重用。 不建议。

有关更多信息,请参见手册页ip(7)tcp(7)

连接池将为您解决此问题。

我想指出, net.ipv4.tcp_tw_recycle已从 Linux 4.12 中完全删除,每次提交95a22caee396

Linux 将随机化每个连接的时间戳偏移量,从而使该选项完全失效,无论有无 NAT。

当远程主机是 NAT 设备时,时间戳条件将禁止除 NAT 设备后面的主机之外的所有主机在一分钟内连接,因为它们不共享相同的时间戳时钟。 毫无疑问,禁用此选项要好得多,因为它会导致难以检测和诊断问题。

资源

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM