Application_Start 在 Azure Web 角色启动时循环
Application_Start loops when Azure web role starts up
我们在 Azure 云服务 Web 角色中有一个 ASP.NET MVC 应用程序 运行ning。 MvcApplication.Application_Start()
中有很多启动代码,其中包括数据库初始化,这可能需要几分钟或更长时间 运行。
有时,当角色实例启动时(部署时或重启后),应用程序第一次启动失败。我们可以从日志中看到 Application_Start
触发,通过某种方式,然后再次从头开始。重复此过程几次后,应用程序通常会完成其启动例程并开始处理请求,但有时它会进入看似永无止境的循环,唯一的解决方案是重新启动或重新映像角色实例。
我们没有看到任何错误被记录,并且Application_End
根本没有触发。每次 Application_Start
触发时,Serilog 的 HttpRequestIdEnricher 都会记录不同的请求 ID,表明每次都有一个新的 HttpContext.Current
。 运行在本地,仅在 Azure 中,我从未见过这种行为。
知道发生了什么吗?
更新
此行为似乎仅在网站上触发多个请求时才会发生。当生产中的角色实例重新启动时,它最常见(并且令人恼火)发生; UAT 环境通常启动良好,但我可以通过在不同的浏览器选项卡中发出多个请求来引发此问题。我还尝试实施类似 this 的方法 - 使 WebRole.OnStart
ping 网络 URL 以确保该站点在退出前 运行ning - 但这只能确保该站点 从未出现。
所以我的猜测是 IIS 是罪魁祸首:当 Application_Start 正在进行时收到新请求时,它似乎正在重新启动应用程序而不是让原始请求完成。
我似乎已经追踪到 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
做同样的事情,但我没试过。
我们在 Azure 云服务 Web 角色中有一个 ASP.NET MVC 应用程序 运行ning。 MvcApplication.Application_Start()
中有很多启动代码,其中包括数据库初始化,这可能需要几分钟或更长时间 运行。
有时,当角色实例启动时(部署时或重启后),应用程序第一次启动失败。我们可以从日志中看到 Application_Start
触发,通过某种方式,然后再次从头开始。重复此过程几次后,应用程序通常会完成其启动例程并开始处理请求,但有时它会进入看似永无止境的循环,唯一的解决方案是重新启动或重新映像角色实例。
我们没有看到任何错误被记录,并且Application_End
根本没有触发。每次 Application_Start
触发时,Serilog 的 HttpRequestIdEnricher 都会记录不同的请求 ID,表明每次都有一个新的 HttpContext.Current
。 运行在本地,仅在 Azure 中,我从未见过这种行为。
知道发生了什么吗?
更新
此行为似乎仅在网站上触发多个请求时才会发生。当生产中的角色实例重新启动时,它最常见(并且令人恼火)发生; UAT 环境通常启动良好,但我可以通过在不同的浏览器选项卡中发出多个请求来引发此问题。我还尝试实施类似 this 的方法 - 使 WebRole.OnStart
ping 网络 URL 以确保该站点在退出前 运行ning - 但这只能确保该站点 从未出现。
所以我的猜测是 IIS 是罪魁祸首:当 Application_Start 正在进行时收到新请求时,它似乎正在重新启动应用程序而不是让原始请求完成。
我似乎已经追踪到 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
做同样的事情,但我没试过。