Search code examples
node.jsiisangular-universalwindows-server

Why node.js does not load website after a server restart?


I use Windows Server Standard 2019 to host an Angular 11 Universal with ASP.net Core 3.1.1 website. The website was working great until a server restart. I did many tests to make sure there is no memory leak or some error from the angular app and everything is absolutely perfect. Then I had to restart the server to install some windows updates and then the website was not working anymore. It does an infinite loading.

The thing is if I kill the Node.js JavasScript Runtime running in Background processes which run after the server has restarted and immediately refresh the website, Node will launch a new process and the website will works as expected until the next server restart. I made many other tests to found that specific case scenario.

So, I am not sure how to solve this. Naturally, I want the website to work immediately after a server restart without any intervention from my side. Here are the files and configurations I guess should help to aim the problem, let me know if you need other info:

Website the folder structure:

  • dist (folder)
  • iisnode (folder)
  • main.js
  • node_start.cmd
  • Web.config

I installed nodejs 14.16.0 LTS first then 15.11.0 Current and also Url Rewrite 2.1 and iisnode-full-v0.2.21-x64

The IIS is version 10. I tried setting the Application Pools to:

  • Start application pool immediately
  • Start mode: AlwaysRunning
  • Idle Time-out Action: Suspend
  • Maximum Worker Processus: 0
  • Preload Enabled: True

I repeat the website works as expected when I kill the Node.js JavasScript Runtime in the background which run after the server has restarted and then hit refresh to reach the website. Finally, the website works with a valid SSL certificate.

Here the content of node_start.cmd

cd "C:\inetpub\wwwroot\championstogether" "C:\Program Files\nodejs\node.exe" "C:\inetpub\wwwroot\championstogether\main.js"

Then the Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
    <system.webServer>        
      <handlers>
                <add name="StaticFilesCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />  
                <add name="StaticFilesPng" path="*.png" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
        <add name="iisnode" path="main.js" verb="*" modules="iisnode" responseBufferLimit="0" />
      </handlers>
      <iisnode nodeProcessCommandLine="C:\Program Files\nodejs\node.exe --no-deprecation --no-warnings" 
        flushResponse="false" 
                promoteServerVars="HTTP_UID,HTTP_PUBCOOKIE_USER,LOGON_USER,HTTP_SHIBSESSIONID"
                node_env="production"
                nodeProcessCountPerApplication="0"
                debugHeaderEnabled="false"
                devErrorsEnabled="false"
        gracefulShutdownTimeout="60000"
        maxConcurrentRequestsPerProcess="1024"
        maxNamedPipeConnectionRetry="100"
        namedPipeConnectionRetryDelay="250"
        maxNamedPipeConnectionPoolSize="512"
        maxNamedPipePooledConnectionAge="30000"
        asyncCompletionThreadCount="0"
        initialRequestBufferSize="4096"
        maxRequestBufferSize="65536"
        uncFileChangesPollingInterval="5000"
        loggingEnabled="true"
        logDirectory="iisnode"
        debuggingEnabled="true"
        debuggerPortRange="5058-6058"
        debuggerPathSegment="debug"
        maxLogFileSizeInKB="128"
        maxTotalLogFileSizeInKB="1024"
        maxLogFiles="20"
        enableXFF="false"
        configOverrides="iisnode.yml"
                watchedFiles="web.config;*.js;routes\*.js;views\*.pug"/>
      <rewrite>
        <rules>
            <rule name="DynamicContent">
                 <match url="/*" />
                 <action type="Rewrite" url="main.js" />
            </rule>
            <rule name="StaticContent" stopProcessing="true">  
                  <match url="([\S]+[.](jpg|jpeg|gif|css|png|js|ts|cscc|less|ico|html|map|svg))" />
                  <action type="None" />
            </rule>
         <rule name="SocketIO" patternSyntax="ECMAScript">
               <match url="socket.io.+"/>
            <action type="Rewrite" url="main.js"/>
         </rule>
          <!-- Don't interfere with requests for node-inspector debugging -->
          <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
            <match url="^main.js\/debug[\/]?"/>
          </rule>
       </rules>
      </rewrite>
      <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />
    <modules runAllManagedModulesForAllRequests="false" />
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" />
      <remove fileExtension=".svg" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".ttf" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <remove fileExtension=".otf" />
      <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".woff" mimeType="application/x-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/x-woff" />
      <mimeMap fileExtension=".otf" mimeType="application/otf" />
     </staticContent>    
    </system.webServer>
    </location>
  </configuration>

Thank you for any help,

Samantha


Solution

  • Based on @killshot13 answer, I got nodejs to work with HttpPlatformHandler. The website takes maybe 3 minutes to load the first time after a server restart. I'm little disapointed about not being able to configure nodejs with nodeProcessCountPerApplication="0" or flushResponse="false" but perhaps someone else know how.

    So here the answer :

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    <location path="." inheritInChildApplications="false">
        <system.webServer>        
          <handlers>
            <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
          </handlers>
          <httpPlatform 
               arguments=".\main.js"
               stdoutLogEnabled="true"
               stdoutLogFile=".\node.log"
               startupTimeLimit="20"
               startupRetryCount="10"
               rapidFailsPerMinute="10"
               requestTimeout="00:02:00"
               processesPerApplication="2"
               processPath="C:\Program Files\nodejs\node.exe --no-deprecation --no-warnings">
                <environmentVariables>
                    <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
                    <environmentVariable name="NODE_ENV" value="production" />
                </environmentVariables>            
            </httpPlatform>
          <!-- Make sure error responses are left untouched -->
        <httpErrors existingResponse="PassThrough" />
        <modules runAllManagedModulesForAllRequests="false" />
        <staticContent>
          <clientCache cacheControlMode="UseMaxAge" />
          <remove fileExtension=".svg" />
          <remove fileExtension=".eot" />
          <remove fileExtension=".ttf" />
          <remove fileExtension=".woff" />
          <remove fileExtension=".woff2" />
          <remove fileExtension=".otf" />
          <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
          <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
          <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
          <mimeMap fileExtension=".woff" mimeType="application/x-woff" />
          <mimeMap fileExtension=".woff2" mimeType="application/x-woff" />
          <mimeMap fileExtension=".otf" mimeType="application/otf" />
         </staticContent>    
        </system.webServer>
        </location>
        <system.webServer>
            <defaultDocument>
                <files>
                    <clear />
                    <add value="index.html" />
                    <add value="index.htm" />
                    <add value="iisstart.htm" />
                    <add value="default.aspx" />
                </files>
            </defaultDocument>
        </system.webServer>
      </configuration>