我们有一个在Azure云服务Web角色中运行的ASP.NET MVC应用程序。 MvcApplication.Application_Start()
中有很多启动代码,在其他事情中进行数据库初始化,这可能需要几分钟或更长时间才能运行。
有时,当角色实例启动时(部署或重启后),应用程序无法首次启动。我们可以从日志中看到Application_Start
触发,获取某种方式,然后从头开始。在重复此过程几次之后,应用程序通常会完成其启动例程并开始处理请求,但偶尔会进入一个看似永无止境的循环,唯一的解决方案是重新启动或重新映像角色实例。
我们不看到记录的任何错误,Application_End
根本没有触发。每次Application_Start
触发时,Serilog的HttpRequestIdEnricher都会记录不同的请求ID,表示每次都有新的HttpContext.Current
。我在本地运行时从未见过这种行为,仅在Azure中。
任何想法发生了什么?
只有在网站上发出多个请求时,才会出现此行为。当重新启动生产中的角色实例时,最常见(并且令人愤怒); UAT环境通常启动正常,但我可以通过在不同的浏览器选项卡中发出多个请求来激发此问题。我还尝试实施类似this的内容 - 让WebRole.OnStart
ping网页网址以确保网站在退出之前运行 - 但这只能确保网站永远不会出现。< / p>
所以我的猜测是IIS应该受到指责:当Application_Start正在进行时出现新请求时,它似乎正在重新启动应用程序,而不是让原始请求完成。
答案 0 :(得分:2)
我似乎已将此跟踪到IIS应用程序池配置中的一个或两个设置。
我最初假设Startup Time Limit
是最可能的罪魁祸首,并尝试将其设置为240秒(因为我们的应用程序通常需要2-3分钟才能启动),但问题仍然存在。我随后也将Ping Maximum Response Time
改为240秒,这似乎已经治好了。
当启动陷入循环时,通常(并非总是)连续启动之间的间隔为2分钟,因此我假设IIS等待30秒(默认为Ping Period
),然后发出请求并且在重新启动工作进程之前等待90秒的响应。
此Powershell代码在Web角色启动时运行的脚本中配置相关设置:
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools | ForEach-Object {
$appPool = "IIS:\AppPools\" + $_.Name
$startupLimit = New-TimeSpan -Minutes 4
Set-ItemProperty $appPool -Name processModel.startupTimeLimit -Value $startupLimit
Set-ItemProperty $appPool -Name processModel.pingResponseTime -Value $startupLimit
}
应该可以对Microsoft.Web.Administration.ServerManager
做同样的事情,但我还没有尝试过。