使用 Kestrel 时发生的 .NET 6 Web 应用程序崩溃

问题描述 投票:0回答:1

我有一个 .NET 6 Web 应用程序,在使用 Kestrel 时间歇性崩溃:

System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.<GetResult>g__ThrowSocketException|5_0(SocketError e)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.GetResult(Int16 token)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketConnection.DoReceive()
   at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
   at System.IO.Pipelines.Pipe.GetReadAsyncResult()
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
         at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.<GetResult>g__ThrowSocketException|5_0(SocketError e)
         at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.GetResult(Int16 token)
         at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketConnection.DoReceive()
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
Microsoft.AspNetCore.Server.Kestrel: Warning: Connection processing ended abnormally.

我无法可靠地导致它发生,但它最终总是会发生,通常是在跑步 5-20 分钟后。网络应用程序完全停止,这是我们可以从任何日志记录中得到的最后一条消息。

这看起来像是某种套接字连接错误,但它发生在本地计算机上,它发生在附加的 VSCode 或 VS2022 调试器上。

整个堆栈都指向 Microsoft 代码,其中没有任何部分指向我们应用程序中的代码。

知道从哪里开始解决这个问题吗?可能是什么原因造成的?

asp.net .net-6.0 kestrel-http-server
1个回答
0
投票

造成这种情况的原因是 .NET 中埋藏着一把枪,对于从 .NET Core 升级到现代 .NET 的任何人来说

我们发现

dotnet.exe
w3wp.exe
正在创建数百个 IPv4 环回连接。最终他们用完了,我们就会遭遇这次事故。

Kestrel 的早期版本不在 IIS 中运行 - 相反,IIS 会运行代理并将连接传递到 Kestrel(更多内容请参阅此 answer)。该代理有一个相当严重的错误 - 取消令牌会导致 IIS 关闭连接并继续,但 IIS 不会告诉 Kestrel,它只会继续运行。

每次发生取消令牌时,

w3wp.exe
都会取消环回连接,但
dotnet.exe
将继续执行其正在处理的任何缓慢的操作。与此同时,对于我们的用户来说,事情会变得更慢(更多的是排队),因此他们会离开,取消另一个请求并使队列变得更糟。

但是我们现在使用的是.NET7,它应该正在运行,对吧?

首先,我们在启动时仍然使用

WebHost.CreateDefaultBuilder
(.NET Core 方法)而不是
WebApplication.CreateBuilder
(自 .NET6 以来的新方法) - 旧的 Core 方法默认为 Kestrel 在进程外运行。

所以我们修复了这个问题并且它仍然发生了。

我们错过了

web.config
这里也有一个设置:

<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />

这导致 Kestrel 仍然会在进程外运行,并且每当发生太多导航取消时就会崩溃。

最终修复是:

<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />

一旦我们完成了所有这些,它就终于被修复并不再发生了。如果您发现自己遇到同样的问题,请调试您的代码并检查当前进程名称 (

Process.GetCurrentProcess().ProcessName
) - 如果它是
w3wp.exe
很好,那么您正在 IIS 中运行,但如果您使用的是 IIS 并且您会得到
dotnet.exe
相反,这意味着它会退回到进程外模式,并且(如果您使用取消令牌)您可能会看到与连接池相关的相同崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.