使用 Node Js 的 AWS Lambda 在 http.request() 上给出 "connect ETIMEDOUT"

AWS Lambda using Node Js gives "connect ETIMEDOUT" on http.request()

我编写了 lambda 函数来检索 s3 Url 每当在 s3 存储桶上创建任何新对象时。 检索 s3Url 后,此 lambda 通过 REST 调用向我的服务器发出请求。

我观察了观云者。 无法向我的服务器发送请求 我不想在我的 lambda 中使用外部包,我想让它轻量级,这就是我使用 nodeJ 的原因 https.

这是我的 Lambda 代码

 exports.handler =  (event,context,callback) => {
  // Extract S3 Url and id From S3 object present in event
  const https = require('https');
  let {s3 , awsRegion} = event["Records"][0];
  let {object : {key}, bucket : {name}} = s3;
  let s3URL = `https://${name}.s3.${awsRegion}.amazonaws.com/${key}`;
  console.log("sURL",s3URL);
  let _id = key.split('/')[0];
  console.log("id",_id);
//Making http request to my server
  let body='';
  // the post options
  let optionsPost = {
     host: 'xyz.abc.com', 
    path: '/api/v1/apipath',
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Authorization': 'XYZ',
    'id' : _id
  }
  };
  const keepAliveAgent = new https.Agent({ keepAlive: true });
  optionsPost.agent = keepAliveAgent;
  let reqPost =  https.request(optionsPost, function(res) {
      console.log("statusCode: ", res.statusCode);
      res.on('data', function (chunk) {
          body += chunk;
      });
      res.on('end', function () {
        console.log("Result", body.toString());
         context.succeed("Sucess")
      });
       res.on('error', function () {
        console.log("Result Error", body.toString());
        context.done(null, 'FAILURE');
        callback(new Error('failure')) // to return error
      });
  });
  reqPost.write(JSON.stringify({ s3Url: s3URL,userName: 'SYSTEM' }));
  reqPost.end();
};

这是我的云观察者错误

{ "errorType": "Error", "errorMessage": "connect ETIMEDOUT 34.255.225.41:443", "code": "ETIMEDOUT", "errno": "ETIMEDOUT", "syscall": "connect", "address": "34.255.225.41", "port": 443, "stack": [ "Error: connect ETIMEDOUT 34.255.225.41:443", " at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14)" ] }

如果您尝试通过 AWS SDK 或直接通过来自 Lambda 的任何 HTTP 调用访问 S3(或任何其他 AWS 资源),则必须满足以下两种情况之一:

  • 您的 Lambda 未在 VPC运行 中设置
  • 您的 Lambda 在 VPC 中设置为 运行,并且 VPC 设置为 NAT gateway

在 AWS 中,VPC 提供了一个“public”网络和一个“私有”网络,其中所有资源都位于VPC 可以与 VPC 中的其他资源进行通信,而不管它们在哪个网段上。 VPC 的 public 段上的任何资源都将通过大多数 VPC 上提供的开箱即用的 Internet 网关路由 public-internet 绑定流量。但是,在 VPC 的 私有 网段上设置的任何 containers/resources 都受到防火墙保护,并且在不安装 NAT 的情况下没有 public 互联网地址的路由。

当您在 VPC 中调用配置为 运行 的 Lambda 函数时,运行 代码所在的容器会在 VPC私有段。因此,如果没有 NAT,Lambda 只能通过其内部 IP addresses/DNS 名称访问 VPC 内的任何资源。

由于所有 AWS 服务资源通常都是从其面向 public 的服务域名(例如从 AWS S3)访问的,因此尝试在没有 NAT 网关的 VPC 后面的 Lambda 中访问它们将导致您的函数收到 ETIMEDOUT 个错误。

出于同样的原因,在 Lambda 中使用 AWS SDK 时也会发生这种情况。

如果您的函数需要在 VPC 后面访问其他资源,那么您应该在 VPC 上设置 NAT 网关。有关如何执行此操作的更多信息,请参阅 AWS Documentation。否则,您应确保您的 Lambda 设置为使用 VPC,因为 运行将其置于 VPC 内会导致额外的冷启动时间延迟以及网络连接挑战.