ASP.. NET Core MVC应用请求永远不会完成

本文关键字:永远 请求 NET Core MVC 应用 ASP | 更新日期: 2023-09-27 18:04:20

我正在尝试托管一个ASP。. NET Core MVC项目在单核Windows Server 2012主机上。我用的是ASP。.NET Core MVC 1.0.0,在iis8和。NET Framework 4.6.1上运行应用程序在最初的10分钟内工作正常,然后突然服务器停止响应。

一开始我以为是数据库端死锁,所以我在DbContext类中添加了日志记录:

private static long ActiveContextCount = 0;
private ILogger _log;
private Stopwatch _timer = new Stopwatch();
private Guid _contextId = Guid.NewGuid();
public BlogContext(string nameOrConnectionString, ILoggerFactory logger)
        :base(nameOrConnectionString)
{
    _log  = logger.CreateLogger<BlogContext>();
    Database.Log = l =>
    {
        _log.LogInformation(l);
    };
    ActiveContextCount++;
    _timer.Start();
    _log.LogInformation("BlogContext created. GUID:{0}, Active count {1}", _contextId, ActiveContextCount);
}
protected override void Dispose(bool disposing)
{
    ActiveContextCount--;
    _timer.Stop();
    _log?.LogInformation("BlogContext Disposed. GUID:{0}, Live time: {1}ms, Active count {2}", _contextId, _timer.ElapsedMilliseconds, ActiveContextCount);
    base.Dispose(disposing);
}

我正在使用实体框架6,我已经设置了DbContext的范围:

services.AddScoped(p => new BlogContext(_dataDbConnectionString, p.GetRequiredService<ILoggerFactory>()));

结果表明,DB操作都工作正常。我在日志中跟踪请求,注意到一些请求的最后日志为:

[Information] Executing ViewResult, running view at path "/Views/Blog/Details.cshtml".

并且永远不会完成(即在日志中找不到dispose)。从那时起,ActiveContextCount只会堆积到几百个,整个应用程序会挂起并停止响应。

(EDIT 08/29)另一个例子,甚至没有执行任何查询:

[Information] Request starting HTTP/1.1 GET http://myapp/  
[Information] UsersContext created. GUID:bb7743b9-7999-4a01-819f-3d239d34d4d9, Active count 7
[Information] HttpContext.User merged via AutomaticAuthentication from authenticationScheme: "Identity.Application".
[Information] BlogContext created. GUID:8c7505d4-5c87-428e-ad56-12f35f54aadc, Active count 6
[Information] Executing action method "MyApp.Controllers.HomeController.Index (MyApp)" with arguments (["1"]) - ModelState is Valid
[Information] Executing ViewResult, running view at path "/Views/Home/Index.cshtml".

我在这一点上卡住了。为什么视图结果永远不会结束?这是一个bug在框架或我的应用程序?即使存在错误,为什么不在超时后中止并放弃请求呢?我试图在web中指定超时时间。配置但没有帮助:

<aspNetCore processPath=".'MyApp.exe" arguments="" forwardWindowsAuthToken="false" stdoutLogEnabled="false" stdoutLogFile=".'logs'stdout" requestTimeout="00:00:40" />

如何进一步调试此问题?

ASP.. NET Core MVC应用请求永远不会完成

经过几周的调试,我终于找到了问题所在。问题确实存在于视野中。我浏览了asp.net core文档,注意到这一行:

PartialAsync方法可用于包含异步代码的部分视图(尽管通常不鼓励在视图中编写代码)。

然后我去看看Html.Partial在github上的实际实现。

var result = htmlHelper.RenderPartialAsync(partialViewName, htmlHelper.ViewData.Model, viewData);
result.GetAwaiter().GetResult();

所以同步部分实际上只是对异步版本的阻塞包装!这是经典的异步等待死锁(1),因为我在部分视图中调用@await Component.InvokeAysnc(因为没有用于调用视图组件的同步版本)。我已经将所有的Html.Partial引用替换为await Html.PartialAsync,问题解决了。我真的希望他们能有更好的警告…(

注:我没有发布超过2个链接的声誉,但为什么…

(1): blog.stephencleary.com/2012/07/dont-block-on-async-code.html