【问题标题】:Kestrel fails to bind port after server restart服务器重启后,Kestrel 绑定端口失败
【发布时间】:2019-12-13 10:57:58
【问题描述】:

美好的一天。

我遇到了 ASP.NET Core WebAPI 服务器的问题。当我重新启动 Web 服务器时,大约 80% 的时间会发生这种情况。
不会发生在任何本地 Windows 机器上。

技术细节:

服务器在 Ubuntu Linux 上运行:

NAME="Ubuntu"
VERSION="16.04.6 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.6 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

点网信息:

~# dotnet --version
2.2.203

~# dotnet --list-sdks
2.0.3 [/usr/share/dotnet/sdk]
2.1.4 [/usr/share/dotnet/sdk]
2.2.203 [/usr/share/dotnet/sdk]

为 .NET Core 2.0 构建的服务器本身

出现的问题:

服务器重启后,Kestrel 绑定端口失败。我在 2001 端口绑定它。

来自journalctl的日志:

Unhandled Exception: System.IO.IOException: Failed to bind to address http://[::]:2001: address already in use. ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use ---> System.Net.Sockets.SocketException: Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransport.BindAsync()
   --- End of inner exception stack trace ---

我该如何解决:

我真的无能为力。我必须等待几分钟(它会重新启动并崩溃几次),然后服务器将正常启动,就像什么都没发生一样。

我尝试过的:

我创建了一个小代码,尝试在启动 Kestrel 之前绑定端口。
如果失败,它会稍等片刻,然后再试一次。基本上它会等到端口被释放。
当绑定成功时,它会释放端口并尝试启动 Kestrel。
这段代码在我的机器上运行良好,但在远程 Linux 机器上不起作用。

我最好的猜测是它与 IPv6 有关,但我真的不知道到底是什么。

(Kestrel 在 Windows 上完美重启(在本地网络中使用 IPv4 地址)并在 Linux 上失败(使用 IPv6 本地地址))

我将不胜感激。

【问题讨论】:

  • 我会从客户端做的是从 cmd.exe >ping -t IP 运行 ping。 -t 选项连续运行 ping。然后重新启动服务器几次,看看 ping 需要多长时间才能开始工作。尝试在window和linux上。我不确定是服务器花了很长时间才开始识别 IP,还是存在未关闭并最终超时的现有连接。
  • 停止服务器后,您的连接可能处于 TIME_WAIT 状态。这是为了处理可能仍在网络中传输的数据包。不同的操作系统有不同的实现如何限制使用相同的端口号。 Linux 比 Windows 更严格。要重用相同的端口,您必须在服务器代码中调用 bind 之前设置套接字选项 SO_REUSEADDR 和/或 SO_REUSEPORT。 (我不知道如何在 C# 中执行此操作。)请参阅 serverframework.com/asynchronousevents/2011/01/…
  • @jdweng Ping 不会做任何与端口打开或关闭相关的事情。
  • @Bodo 会检查的,谢谢!
  • 除非 PING 有效,否则您无法打开或关闭端口。所以 PING 与端口的打开或关闭有关。如果您没有到服务器的路由,则 ping 将不起作用,并且打开/关闭将不起作用。

标签: c# linux sockets ubuntu asp.net-core


【解决方案1】:

强制杀死方法:

如果你想找到连接到端口的东西,在 ubuntu 上使用:

lsof -i :2001

它将同时显示 IPv4 和 IPv6。寻找“听”

一旦您确认您不关心之前在那里收听的内容,您就可以强制清除端口作为启动前例程的一部分。

lsof -ti :2001 | xargs --no-run-if-empty kill -9

【讨论】:

  • 似乎服务器由于无限线程而没有停止。这对我有帮助。谢谢。
  • 将奖励您的答案是 13 小时。
猜你喜欢
  • 1970-01-01
  • 2020-12-07
  • 2018-09-27
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多