c# - ASP.NET Core 3.1 InProcess 托管应用程序在启动异常后未重新启动

标签 c# asp.net iis .net-core

问题

我有一个使用 IIS 托管的 InProcess ASP.NET Core Web 应用程序。我实现了每次启动时抛出的异常。 不出所料 , IIS 显示这个错误页面:

HTTP Error 500.30 - ANCM In-Process Start Failure

Common solutions to this issue:

  • The application failed to start
  • The application started but then stopped
  • The application started but threw an exception during startup

Troubleshooting steps:

  • Check the system event log for error messages
  • Enable logging the application process' stdout messages
  • Attach a debugger to the application process and inspect

For more information visit: https://go.microsoft.com/fwlink/?LinkID=2028265



在 .Net Core 2.2(带有 CaptureStartupErrors(false))以及经典的 ASP.NET 应用程序中,IIS 尝试在下一个请求时再次启动应用程序。

对于 .Net Core 3.1,它不会 尝试重新启动,无论我为 CaptureStartupErrors 设置什么,它都会永远保持这种状态。 .

解决方法

我可以通过捕获异常并退出来解决此问题 - 如果我这样做,它将按预期运行:
public static void Main(string[] args)
{
    try
    {
        CreateWebHostBuilder(args).Build().Run();
    }
    catch (Exception)
    {
        Environment.Exit(-1);
    }
}

预期行为

对于如何更改此行为的任何想法,我都很高兴,因此在不使用此解决方法的情况下,它的行为与以前相同。如果我的应用程序抛出一个未处理的异常,它应该退出并尝试在下一个请求时重新启动。

我试过的
  • CaptureStartupErrors 使用不同的值
  • 查找更改此行为的配置参数
  • 在“发布”-配置中发布而不是“调试”
  • 创建了一个 issue on Github

  • 重现问题的代码

    Repository on Github

    当您将应用程序发布到 IIS 时会出现此问题,并且在没有 IIS 的情况下无法重现。

    程序.cs:
    public class Program
    {
        public static void Main(string[] args)
        {
            File.AppendAllText("log.txt", $"{DateTime.Now.ToLongTimeString()}:Starting\r\n");
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateWebHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder( args )
                .ConfigureWebHostDefaults( webBuilder =>
                {
                    webBuilder
                        .UseStartup<Startup>();
                } );
    }
    

    启动.cs:
    public class Startup
    {
        public Startup( IConfiguration configuration )
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        public void ConfigureServices( IServiceCollection services )
        {
    
        }
    
        public void Configure( IApplicationBuilder app, IHostingEnvironment env )
        {
            throw new Exception();
    
        }
    }
    

    以下文件大多是默认的,但如果你想检查:

    网络配置:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <handlers>
            <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
          </handlers>
          <aspNetCore processPath="dotnet" arguments=".\WebApplication20.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
        </system.webServer>
      </location>
    </configuration>
    

    .csproj:
    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
      </ItemGroup>
    
    </Project>
    

    FolderProfile.pubxml:
    <?xml version="1.0" encoding="utf-8"?>
    <!--
    https://go.microsoft.com/fwlink/?LinkID=208121. 
    -->
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <DeleteExistingFiles>False</DeleteExistingFiles>
        <ExcludeApp_Data>False</ExcludeApp_Data>
        <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
        <LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
        <LastUsedPlatform>Any CPU</LastUsedPlatform>
        <PublishProvider>FileSystem</PublishProvider>
        <PublishUrl>C:\inetpub\wwwroot\test</PublishUrl>
        <WebPublishMethod>FileSystem</WebPublishMethod>
        <SiteUrlToLaunchAfterPublish />
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <ProjectGuid>9ec27b57-5f45-4286-aa7c-12abad61a153</ProjectGuid>
        <SelfContained>false</SelfContained>
      </PropertyGroup>
    </Project>
    

    最佳答案

    如微软 did explain in my issue这是预期的行为:

    I believe this behavior is expected and is a behavior difference between IIS Out-of-process and In-Process. However, we could consider trying to change the behavior for in-process.

    In 2.2, it sounds like you were using IIS out-of-process, as you said you saw this behavior with Full Framework. ANCM will constantly try to restart the dotnet process if it crashes.

    However, in 3.1/in-process, if the application crashes on Startup, ANCM will not restart the process if it crashes on Startup. This is for a few reasons:

    Because we are running in-process, we need to restart the w3wp.exe/iisexpress.exe process entirely as we can't start the dotnet runtime twice without possibility for bad behavior. Constantly restarting the w3wp process is usually not a good idea. We made an assumption that if a process throws an unhandled exception on startup, we should required the app to be redeployed before trying again. This may not have been the right decision at the time, but it is a key reason for the behavior change.



    因此,我的问题的解决方案是使用变通方法或以另一种方式处理异常。如果您决定使用该解决方法,您应该知道 IIS 有一个 configurable rapid failure protection如果应用程序池重启太频繁,则停止应用程序池。

    AFAIK, the code you have to call Environment.Exit(-1) may work for a few tries, however I believe that after calling that a few times, IIS will trigger Rapid Failure protection which will force the site not to start again.

    关于c# - ASP.NET Core 3.1 InProcess 托管应用程序在启动异常后未重新启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62169080/

    相关文章:

    iis - 奇怪的 '` '.dll 文件在 bin 文件夹中,ASP.Net MVC

    c# - 使用 SSL 加密在 IIS 10 上托管 WCF 服务库

    iis - IIS下ASP.NET Core随机重启

    C# 在 Deedle Frame 和 DataTable 之间转换

    c# - 使用 ISerializable 反序列化 .NET 字典

    在 iis 中托管后 CSS 不引用

    asp.net - 如何使用 web 服务返回接口(interface)或 "complex"值?

    c# - 使用 Entity Framework 4.0/.edmx 从 c# 调用标量函数

    c# - 基本方法是否能够使用派生的基本数据成员?

    c# - onselectedindexchanged() 未被调用,即使单击取消按钮,确认框也会清除文本