iisnode 上的 NestJs 安装和未处理的承诺拒绝

NestJs installation on iisnode and Unhandled promise rejection

当我尝试在 IIS 服务器(安装了 iisnode)上安装 NestJs 应用程序时,我总是遇到这样的问题 “...错误:听 EADDRINUSE:地址已在使用中::3450 ..”(见下文) 而且,正如您从 console.log 中看到的(见下文),NestJs 应用程序首先完全初始化并启动,但随后总是出现端口已被使用的问题。无论我尝试多少个不同的端口,它都会持续存在。我也尝试重新启动 iisnode.exe 并终止进程和端口,但它没有帮助。有人对此有任何经验并找到了解决方案吗?

node dist/main

[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[NestFactory] [39m[32mStarting Nest application...[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[InstanceLoader] [39m[32mConfigHostModule dependencies initialized[39m[33m +34ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[InstanceLoader] [39m[32mAppModule dependencies initialized[39m[33m +0ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[InstanceLoader] [39m[32mConfigModule dependencies initialized[39m[33m +1ms[39m
hello from NestJs app
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RoutesResolver] [39m[32mAppController {}:[39m[33m +13ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RouterExplorer] [39m[32mMapped {, GET} route[39m[33m +4ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RoutesResolver] [39m[32mItemsController {/items}:[39m[33m +0ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RouterExplorer] [39m[32mMapped {/items, GET} route[39m[33m +1ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RouterExplorer] [39m[32mMapped {/items/:id, GET} route[39m[33m +2ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RouterExplorer] [39m[32mMapped {/items, POST} route[39m[33m +1ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RoutesResolver] [39m[32mShoppingCartController {/shopping-cart}:[39m[33m +1ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[RouterExplorer] [39m[32mMapped {/shopping-cart, POST} route[39m[33m +0ms[39m
[32m[Nest] 36096   - [39m09/01/2020, 1:43:54 PM   [33m[NestApplication] [39m[32mNest application successfully started[39m[33m +4ms[39m
App is running in port: 61302
events.js:292
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE: address already in use :::61302
    at Server.setupListenHandle [as _listen2] (net.js:1313:16)
    at listenInCluster (net.js:1361:12)
    at Server.listen (net.js:1447:7)
    at ExpressAdapter.listen (C:\...\node_modules\@nestjs\platform-express\adapters\express-adapter.js:45:32)
    at NestApplication.listen (C:\...\node_modules\@nestjs\core\nest-application.js:146:26)
    at async bootstrap (C:\...\dist\main.js:8:9)
Emitted 'error' event on Server instance at:
    at emitErrorNT (net.js:1340:8)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'EADDRINUSE',
  errno: 'EADDRINUSE',
  syscall: 'listen',
  address: '::',
  port: 61302
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! nest-restaurant-api@0.0.1 start:prod: `node dist/main`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the nest-restaurant-api@0.0.1 start:prod script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\...\AppData\Roaming\npm-cache\_logs20-09-01T12_43_54_285Z-debug.log

在 iisnode 服务器错误日志中我还可以找到以下内容: (这被证明是在前一天记录的 - 并且在日志中再也看不到了。因此,这个 iisnode 日志消息可能与问题根本无关)

(node:45472) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(node:45472) UnhandledPromiseRejectionWarning: RangeError [ERR_SOCKET_BAD_PORT]: options.port should be >= 0 and < 65536. Received NaN.
    at validatePort (internal/validators.js:182:11)
    at Server.listen (net.js:1439:5)
    at ExpressAdapter.listen (C:\...\node_modules\@nestjs\platform-express\adapters\express-adapter.js:45:32)
    at NestApplication.listen (C:\...\node_modules\@nestjs\core\nest-application.js:146:26)
    at async bootstrap (C:\...\dist\main.js:7:5)
(node:45472) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:45472) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

此外,这里是 /dist/main.js 文件的当前形式(我添加了那些 try / catch 语句)。

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@nestjs/core");
const app_module_1 = require("./app.module");
async function bootstrap() {
    try {
        const app = await core_1.NestFactory.create(app_module_1.AppModule);
        await app.listen(parseInt(process.env.PORT) || 8080)
        .catch((e) => {
            console.error(e);
            process.exit(1);
        });
        console.log('App is running in port: ' + process.env.PORT);
    }
    catch (error) {
        console.log("Error message: " + error);
    }
}
bootstrap().catch(e => { 
    console.error(e);
});
//# sourceMappingURL=main.js.map

按照 Bruce Zhang 在他的评论中的建议,我将 post 我自己找到的解决方案。

所以,错误的原因确实很愚蠢。

1.) 使用 Plesk 控制面板(在 IIS-server 中),无论 NestJs 应用程序是部署到站点根目录还是子文件夹(如默认的 dist 文件夹),都必须获取路径设置投影以正确引用:

现在,在上图中,项目的路径设置在部署到子文件夹(即默认构建文件夹 dist)时是正确的。我的错误是应用程序启动文件的路径引用是“/dist/main.js”,因为它应该只是 main.js.

在这个简单的更正应用程序正常启动后,默认 IIS-port(端口 80 和 SSL-protected 连接 443)。 main.ts - 文件不需要任何其他内容,只需以下内容即可通过 process.env.PORT 自动获取的 IIS 默认端口:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    await app.listen(process.env.PORT);
}

bootstrap();

2.) 必须正确配置的第二个简单的事情是 web.config(这在我的例子中最初是正确的):

<?xml version="1.0" encoding="UTF-8"?> 
<configuration>
  <system.webServer>

    <handlers>
      <add name="iisnode" path="dist/main.js" verb="*" modules="iisnode" />
    </handlers>
    
    <iisnode nodeProcessCommandLine="C:\Program Files\nodejs\node.exe"> 
    </iisnode> 
    
    <rewrite>
      <rules>
        <rule name="nestjs">
          <match url="/*" />
          <action type="Rewrite" url="main.js" />
        </rule>
      </rules>
    </rewrite>

  </system.webServer>
</configuration>

我希望这对那些可能对 Plesk 中的 IISnode 设置感到困惑的人有所帮助。这些设置通常适用于所有 Node.js 应用程序,它们不仅限于 node.js 上的上层框架 NestJs,尤其是在 Express 上。但是 IISNode 中的错误消息有时会有点误导,并且很难看清它们。

NestJs 真的很棒,那些必须或喜欢使用 IIS 的人可以轻松地将超现代的 NestJs 后端应用程序部署到 IIS-server,感谢那些实施 IISnode 的人。