首页 > 解决方案 > Node/Express 服务器在变量集之前启动

问题描述

我的 node/express 服务器启动时存在问题,因为它在 IP 地址函数/脚本之前加载服务器,该函数/脚本从 EC2 动态检索 hostIp 完成。所以我对后端的调用都在返回undefined

示例:(search.js)

const awsHost = require('./host.js');

const hostIp = awsHost.getBackendHost();
const host = `http://${ hostIp }:1234`;
console.log(host);
console.log(hostIp);
console.log(awsHost.getBackendHost());

输出:

[nodemon] restarting due to changes...
[nodemon] starting `node src/index.js`
http://undefined:1234
undefined
Server: Success -port 1111
11.123.456.789

这是我的(index.js)的当前状态:

const express = require('express');

const app = express();

app.use(express.static('./web/'));
app.listen(1111, () => console.info('Server: Success -port 1111'));

require('./routes/routes.js')(app);

module.exports = app;

如何强制 NodeawsHost.getBackendHost()在最终服务器启动之前运行该功能并加载它?

编辑(host.js):

const aws = require('aws-sdk');

aws.config.update({ region: 'REGION' });

const getBackendHost = () => {
const ecs = new aws.ECS();
const ec2 = new aws.EC2();

const backendPort = '1234';
const clusterParameters = {
  cluster: 'CLUSTER',
};

ecs.listContainerInstances(clusterParameters, (listContainerError, listContainerData) => {
  if (listContainerError) console.log(listContainerError, listContainerError.stack);
  else {
    const containerInstanceParameters = {
      cluster: clusterParameters.cluster,
      containerInstances: listContainerData.containerInstanceArns
    };
    ecs.describeContainerInstances(containerInstanceParameters, (describeContainerError, describeContainerData) => {
      if (describeContainerError) console.log(describeContainerError, describeContainerError.stack);
      else {
        describeContainerData.containerInstances.forEach((container) => {
          container.remainingResources.forEach((dataSet) => {
            if (dataSet.stringSetValue && dataSet.stringSetValue.includes(backendPort)) {
              const containerInstanceId = {
                InstanceIds: [
                  container.ec2InstanceId
                ]
              };
              ec2.describeInstances(containerInstanceId, (describeInstanceError, describeInstanceData) => {
                if (describeInstanceError) console.log(describeInstanceError, describeInstanceError.stack);
                else {
                  const iP = describeInstanceData.Reservations[0].Instances[0].PrivateIpAddress;
                  console.log(iP);
                  return iP;
                }
                return describeInstanceError;
              });
            }
          });
        });
      }
    });
  }
 });
};

module.exports = {
  getBackendHost
};

标签: node.jsamazon-web-servicesexpress

解决方案


您实际上需要遵循 API 建议的回调约定。节点 AWS API 使用节点样式错误优先回调来执行异步调用。您需要等待这些呼叫完成。

更改您getBackendHost()的接受回调:function(err, host){...}或承诺它。然后在您的应用程序中,等待调用完成并使用回调正确设置主机。

此外,嵌套forEach部分也需要在考虑到异步性的情况下重写。

它将类似于:

// host.js
const aws = require("aws-sdk");

aws.config.update({
  region: "REGION"
});

/*
 * Expect a node style callback of the signature:
 * function(err, ip){...}
 */
function getBackendHost(cb) {
  const ecs = new aws.ECS();
  const ec2 = new aws.EC2();

  const backendPort = "1234";
  const clusterParameters = {
    cluster: "CLUSTER"
  };

  ecs.listContainerInstances(clusterParameters, (listContainerError, listContainerData) => {
    // Bail from error
    if (listContainerError) return cb(listContainerError, null);

    const containerInstanceParameters = {
      cluster: clusterParameters.cluster,
      containerInstances: listContainerData.containerInstanceArns
    };

    ecs.describeContainerInstances(containerInstanceParameters, (describeContainerError, describeContainerData) => {
      // Bail from error
      if (describeContainerError) return cb(describeContainerError, null);


      /*
       * You will also need to rewrite this because you are iterating over async items and still not waiting for them
       */
      describeContainerData.containerInstances.forEach(container => {
        container.remainingResources.forEach(dataSet => {
          if (dataSet.stringSetValue && dataSet.stringSetValue.includes(backendPort)) {
            const containerInstanceId = {
              InstanceIds: [
                container.ec2InstanceId
              ]
            };
            ec2.describeInstances(containerInstanceId, (describeInstanceError, describeInstanceData) => {
              // Bail from error
              if (describeInstanceError) return cb(describeInstanceError, null);

              return cb(null, describeInstanceData.Reservations[0].Instances[0].PrivateIpAddress);
            });
          }
        });
      });
    });
  });
}

module.exports = {
  getBackendHost
};

// index.js
const awsHost = require('./host.js');

const hostIp = awsHost.getBackendHost(function(err, hostIp) {
  // Bail from error
  if (err) return console.error(err);

  const host = `http://${ hostIp }:1234`;
  console.log(host);
  console.log(hostIp);
  console.log(awsHost.getBackendHost());
});


推荐阅读