ASP.NET Core IHostedService + IIS 自动启动功能无法正常工作

3

我有一个托管在IIS 10 Windows Server 2019上的.NET 6 IHostedService。

我希望实现以下目标:

  • 服务器重新启动后启动应用程序
  • iisreset后启动应用程序
  • iisreset /start 后启动应用程序

我按照这里的SO帖子这篇博客文章进行了操作。

关于SO帖子的答案:

  • 我重新启动了服务器
  • 按照所有步骤操作

关于博客文章:

  • 我尝试将CLR设置为“无托管代码”和“v4.0”

我发现其他网站上提到,我必须启用匿名身份验证 - 这也经过了测试(请参见applicationhost.config中的下文)

但是我无法让IIS的此基本功能正常运行。 根据SO帖子和博客文章,似乎它帮助了大多数人。

web.config

<?xml version="1.0" encoding="utf-8"?>
   <configuration>
       <location path="." inheritInChildApplications="false">
           <system.webServer>
               <handlers>
                   <remove name="aspNetCore" />
                   <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
               </handlers>
               <aspNetCore processPath="dotnet" arguments=".\<obfuscated>.dll" 
                           stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" 
                           hostingModel="inprocess">
                   <environmentVariables>
                       <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
                   </environmentVariables>
               </aspNetCore>
            </system.webServer>
        </location>
    </configuration>

applicationhost.config:

<?xml version="1.0" encoding="UTF-8"?>
< ... />
<configuration>
    <system.applicationHost>
        <applicationPools>
            <add name="obfuscated" autoStart="true" managedRuntimeVersion="v4.0" startMode="AlwaysRunning">
                <processModel identityType="SpecificUser" userName="obfuscated" password="obfuscated" idleTimeout="00:00:00" />
            </add>
            <applicationPoolDefaults managedRuntimeVersion="v4.0">
                <processModel identityType="ApplicationPoolIdentity" />
                <recycling logEventOnRecycle="Time, Requests, Schedule, Memory, IsapiUnhealthy, OnDemand, ConfigChange, PrivateMemory">
                    <periodicRestart time="00:00:00" />
                </recycling>
            </applicationPoolDefaults>
        </applicationPools>

        < ... />
      
        <sites>
            <site name="obfuscated" id="1">
                <application path="/" applicationPool="obfuscated" preloadEnabled="true">
                    <virtualDirectory path="/" physicalPath="obfuscated" />
                </application>
                <bindings>
                    <binding protocol="http" bindingInformation="obfuscated" />
                </bindings>
            </site>
            <siteDefaults>
                <logFile logExtFileFlags="Date, Time, ClientIP, UserName, SiteName, ComputerName, ServerIP, Method, UriStem, UriQuery, HttpStatus, Win32Status, TimeTaken, ServerPort, UserAgent, Referer, Host, HttpSubStatus" logFormat="W3C" directory="obfuscated">
                </logFile>
                <traceFailedRequestsLogging directory="obfuscated" />
            </siteDefaults>
            <applicationDefaults applicationPool="DefaultAppPool" />
            <virtualDirectoryDefaults allowSubDirConfig="true" />
        </sites>

        <webLimits />
    </system.applicationHost>

    <system.webServer>

        <asp />

        <caching enabled="true" enableKernelCache="true">
        </caching>

        <cgi />

        <defaultDocument enabled="true">
            <files>
                <add value="Default.htm" />
                <add value="Default.asp" />
                <add value="index.htm" />
                <add value="index.html" />
                <add value="iisstart.htm" />
                <add value="default.aspx" />
            </files>
        </defaultDocument>

        <directoryBrowse enabled="false" />

        <fastCgi />
        <!--
          The <globalModules> section defines all native-code modules.
          To enable a module, specify it in the <modules> section.
        -->
        <globalModules>
            <add name="HttpLoggingModule" image="%windir%\System32\inetsrv\loghttp.dll" />
            <add name="UriCacheModule" image="%windir%\System32\inetsrv\cachuri.dll" />
            <add name="FileCacheModule" image="%windir%\System32\inetsrv\cachfile.dll" />
            <add name="TokenCacheModule" image="%windir%\System32\inetsrv\cachtokn.dll" />
            <add name="HttpCacheModule" image="%windir%\System32\inetsrv\cachhttp.dll" />
            <add name="DynamicCompressionModule" image="%windir%\System32\inetsrv\compdyn.dll" />
            <add name="StaticCompressionModule" image="%windir%\System32\inetsrv\compstat.dll" />
            <add name="DefaultDocumentModule" image="%windir%\System32\inetsrv\defdoc.dll" />
            <add name="DirectoryListingModule" image="%windir%\System32\inetsrv\dirlist.dll" />
            <add name="ProtocolSupportModule" image="%windir%\System32\inetsrv\protsup.dll" />
            <add name="HttpRedirectionModule" image="%windir%\System32\inetsrv\redirect.dll" />
            <add name="StaticFileModule" image="%windir%\System32\inetsrv\static.dll" />
            <add name="AnonymousAuthenticationModule" image="%windir%\System32\inetsrv\authanon.dll" />
            <add name="UrlAuthorizationModule" image="%windir%\System32\inetsrv\urlauthz.dll" />
            <add name="WindowsAuthenticationModule" image="%windir%\System32\inetsrv\authsspi.dll" />
            <add name="IpRestrictionModule" image="%windir%\System32\inetsrv\iprestr.dll" />
            <add name="DynamicIpRestrictionModule" image="%windir%\System32\inetsrv\diprestr.dll" />
            <add name="RequestFilteringModule" image="%windir%\System32\inetsrv\modrqflt.dll" />
            <add name="CustomErrorModule" image="%windir%\System32\inetsrv\custerr.dll" />
            <add name="RequestMonitorModule" image="%windir%\System32\inetsrv\iisreqs.dll" />
            <add name="IsapiModule" image="%windir%\System32\inetsrv\isapi.dll" />
            <add name="IsapiFilterModule" image="%windir%\System32\inetsrv\filter.dll" />
            <add name="ManagedEngine64" image="%windir%\Microsoft.NET\Framework64\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness64" />
            <add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" />
            <add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" />
            <add name="ManagedEngineV4.0_64bit" image="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness64" />
            <add name="ConfigurationValidationModule" image="%windir%\System32\inetsrv\validcfg.dll" />
            <add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" />
            <add name="RewriteModule" image="%SystemRoot%\system32\inetsrv\rewrite.dll" />
            <add name="AspNetCoreModuleV2" image="%ProgramFiles%\IIS\Asp.Net Core Module\V2\aspnetcorev2.dll" />
        </globalModules>

        < ... />

        <security>

            <access sslFlags="None" />

            <applicationDependencies />

            <authentication>

                <anonymousAuthentication enabled="true" userName="IUSR" />

                <basicAuthentication />

                <clientCertificateMappingAuthentication />

                <digestAuthentication />

                <iisClientCertificateMappingAuthentication />

                <windowsAuthentication enabled="false" authPersistNonNTLM="true">
                    <providers>
                        <add value="Negotiate" />
                        <add value="NTLM" />
                    </providers>
                </windowsAuthentication>

            </authentication>

            <authorization>
                <add accessType="Allow" users="*" />
            </authorization>

            <ipSecurity allowUnlisted="true" />

            <isapiCgiRestriction>
                <add path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
                <add path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
                <add path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v4.0.30319" description="ASP.NET v4.0.30319" />
                <add path="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v4.0.30319" description="ASP.NET v4.0.30319" />
            </isapiCgiRestriction>

            < ... />

        </security>

        < ... />

    </system.webServer>
    <location path="" overrideMode="Allow">
        <system.webServer>

        <modules>
          < ... />
        </modules>

        <handlers accessPolicy="Read, Script">
              < ... />
        </handlers>
        </system.webServer>
    </location>

</configuration>

我可以确定的是,你已经设置好了应用程序自动启动的一切。但是你怎么能确定应用程序没有启动呢?也许它已经启动了,只是你没有注意到。请检查IIS的工作进程模块或任务管理器中的w3wp.exe。停止应用程序并确认工作进程已停止。然后在不发送任何请求的情况下启动应用程序。检查进程是否存在。 - Bruce Zhang
由于该应用程序在启动时和接下来的几秒钟内大量记录垃圾日志,我相当确定它会一直保持“空闲”状态,直到我向控制器发送唤醒调用。在此之后,该应用程序开始运行并输出日志。 - pandemic
1个回答

0

您应该在服务器上启用应用程序初始化模块,以便自动重新启动应用程序。

在IIS中,默认情况下,如果20分钟内没有请求发送到应用程序,则应用程序将被挂起。

enter image description here

这个PowerShell脚本可以帮助你保持应用程序的持续运行

## IIS WebAdmin Module
    Import-Module WebAdministration

    $AppPoolInstance = Get-Item IIS:\AppPools\$AppPool

    Write-Output "Set Site PreLoadEnabled to true"
    Set-ItemProperty IIS:\Sites\$Site -name applicationDefaults.preloadEnabled -value True

    Write-Output "Set Recycling.periodicRestart.time  = 0"
    $AppPoolInstance.Recycling.periodicRestart.time = [TimeSpan]::Parse("0");
    $AppPoolInstance | Set-Item

    Write-Output "Set App Pool start up mode to AlwaysRunning"
    $AppPoolInstance.startMode = "alwaysrunning"

    Write-Output "Disable App Pool Idle Timeout"
    $AppPoolInstance.processModel.idleTimeout = [TimeSpan]::FromMinutes(0)
    $AppPoolInstance | Set-Item

    if ($appPoolStatus -ne "Started") {
        Write-Output "Starting App Pool"
        Start-WebAppPool $AppPool
    } else {
        Write-Output "Restarting App Pool"
        Restart-WebAppPool $AppPool
    }

注意:您应该将$AppPool$Site名称更改为您的应用程序名称。


这个链接或许对您有所帮助


应用程序初始化模块也已安装,我在提到“按照SO帖子中的所有步骤”时进行了说明。 - pandemic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接