【问题标题】:Why node.js does not load website after a server restart?为什么 node.js 在服务器重启后不加载网站?
【发布时间】:2021-06-10 18:22:06
【问题描述】:

我使用 Windows Server Standard 2019 托管带有 ASP.net Core 3.1.1 网站的 Angular 11 Universal。该网站运行良好,直到服务器重新启动。我做了很多测试,以确保 Angular 应用程序没有内存泄漏或一些错误,并且一切都绝对完美。然后我不得不重新启动服务器来安装一些 Windows 更新,然后网站就不再工作了。它会无限加载。

问题是如果我杀死 Node.js JavaScript Runtime后台进程 在服务器重新启动后运行 并立即刷新该网站,Node 将启动一个新进程,该网站将按预期运行,直到下一次服务器重新启动。我进行了许多其他测试以找到特定的案例场景。

所以,我不确定如何解决这个问题。自然,我希望网站在服务器重新启动后立即运行,而无需我的任何干预。以下是我认为应该有助于解决问题的文件和配置,如果您需要其他信息,请告诉我:

网站文件夹结构:

  • dist(文件夹)
  • iisnode(文件夹)
  • main.js
  • node_start.cmd
  • Web.config

我先安装了 nodejs 14.16.0 LTS,然后安装了 15.11.0 Current,还安装了 Url Rewrite 2.1iisnode-full-v0.2.21-x64强>

IIS 版本为 10。我尝试将应用程序池设置为:

  • 立即启动应用程序池
  • 启动模式:AlwaysRunning
  • 空闲超时操作:挂起
  • 最大工作进程数:0
  • 已启用预加载:是的

当我在后台终止 Node.js JavaScript 运行时(在服务器重新启动后运行,然后点击刷新以到达网站)时,我重复网站按预期工作。最后,该网站使用有效的 SSL 证书。

这里是node_start.cmd的内容

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

然后是 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>

感谢您的帮助,

萨曼莎

【问题讨论】:

    标签: node.js iis angular-universal windows-server


    【解决方案1】:

    萨曼莎-

    根据您的web.config 文件,我看到您正在使用iisnode 模块。 iisnode 模块实际上有一个错误,需要在服务器重新启动后手动重新启动 Node.js 进程,据我所知,尚未最终开发出修复程序。

    虽然微软现在拥有代码,但他们没有创建它,也没有积极维护它。坦率地说,我很惊讶他们还没有发布关于弃用的官方通知。

    在 IIS 上运行 node.js 应用程序的替代选项是使用 ARR(反向代理)模块或 HttpPlatformHandler 模块。 ARR 非常通用;它不支持 Node.js 特定的变量,甚至不支持在 web.config 中使用 Node 的规范。

    我的建议是使用HttpPlatformHandler 模块,它可以管理任何进程,包括Node,以及任何进出父进程的代理请求。虽然基本上仍然是反向代理,但可以为node.js 进程配置此模块。 web.config 应该看起来像这样。

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    <system.webServer>
        <handlers>
          <add name="httpPlatformHandler" path="main.js" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
            <httpPlatform processPath="C:\Program Files\nodejs\node.exe"
                          arguments="" 
                          startupTimeLimit=20
                          startupRetryCount=10
                          rapidFailsPerMinute=10
                          requestTimeout="00:02:00"
                          stdoutLogEnabled=true
                          stdoutLogFile="httpplatform-stdout"
                          processesPerApplication=0
                          forwardWindowsAuthToken=false>
                <environmentVariables>
                    <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
                    <environmentVariable name="NODE_ENV" value="Production" />
                </environmentVariables>
             </httpPlatform>
         // add the config details for the rest of your module here
      </system.webServer>
    </configuration>
    

    其他参考资料 --

    官方

    Microsoft Documentation

    Download & Support Page

    社区

    Node & IIS Configuration Discussion Thread

    Peter Eyserman's Blog Article

    【讨论】:

    • 我自己永远也找不到,非常感谢!我对 httpPlaform 做了一些尝试,效果很好,但看起来我无法设置大部分 iisnode 参数。我将在本周末展示新的 web.config。
    • 我确实注意到iisnode 提供的一些约束要么不能直接翻译,要么在httpplatform 中完全不存在。这大概是因为后者不是特定于节点的,因此更笼统。希望您可以找到一种替代方法来强制执行所述参数,或者甚至完全消除其中的一些参数。
    【解决方案2】:

    根据@killshot13 的回答,我让nodejs 与HttpPlatformHandler 一起工作。服务器重新启动后,第一次加载该网站可能需要 3 分钟。我对无法使用 nodeProcessCountPerApplication="0" 或 flushResponse="false" 配置 nodejs 有点失望,但也许其他人知道如何。

    所以这里是答案:

    <?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>
    

    【讨论】:

    • 您是否考虑过在arguments 下传递nodeProcessCountPerApplication="0" 和/或flushResponse="false"?该文档对此处可以定义的内容相当模糊;内容如下。 arguments -- "可选字符串值。processPath 设置中指定的可执行文件或脚本的参数。没有默认值。"
    • 这是应该用参数测试的东西,我没有测试。这些参数不适用于 processPath。我还决定切换回 iisnode 并在服务器重新启动时终止 Node.js JavaScript Runtime。我更喜欢访问所有参数以获得更好的性能,因为很少会重新启动服务器。希望微软能看到这一点并采取行动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    相关资源
    最近更新 更多