如何在AWS Lambda函数中进行外部api调用 [英] How to make an external api call within an AWS Lambda function

查看:683
本文介绍了如何在AWS Lambda函数中进行外部api调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了 Lambda函数的问题,出于某种原因,它超时超时.

我试图添加一些console.log来了解正在发生的事情,并且一切正常,直到外部http请求为止.

I tried to add some console.log to understand what was going on and everything works properly until the external http request.

我使用了 npm模块请求

我可以在请求之前看到日志,但是回调中的日志永远不会显示,就像端点没有响应一样.

I can see the log before the request, but the one inside the callback never shows up, like if the endpoint doesn't respond.

我错过了什么吗?预先感谢!

Am I missing something? Thanks in advance!

var mysql = require('mysql'); 
var request = require('request');
var config = require('./config.json'); 

var pool = mysql.createPool({
  host: config.dbhost,
  user: config.dbuser,
  password: config.dbpassword,
  database: config.dbname
});

var openWeatherOptions = (device) => {
    let domain = 'https://api.openweathermap.org/data/2.5/';
    let apiEndpoint = 'weather?';
    let params = `lat=${device.lat}&lon=${device.lng}&APPID=${process.env.WEATHER_APP_ID}&units=metric`;
    let url = [domain, apiEndpoint, params].join('').toString();
    return {
      url: url,
      method: 'GET',
      headers: { 'Content-Type': 'application/json'},
    };
};

exports.handler = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
    // Connect to DB
    console.log('fallback connecting to DB')
    pool.getConnection( (errOnConnection, connection) => {
        if(errOnConnection) {
            callback({"err": errOnConnection });
        }
        console.log('fallback connected to DB')
        // Retrieve device position
        let queryOne = 'SELECT lat, lng FROM T03_DevicesPosition WHERE deviceCode = (?);';
        console.log('fallback retrieving device position')
        connection.query( queryOne, [event.device], (errOnQ1, results, fields) => { 
            if(errOnQ1) {
                connection.release();
                callback({"err": errOnQ1 });
            }
            console.log('fallback device position retrieved')

            // Call openweather 
            let device = results[0];
            let options = openWeatherOptions(device);
            console.log('fallback calling openWeather with following data: ', device, options);

            request( options, (errOpenWeather, response, body) => {
                console.log('fallback openweather response received');
                if(errOpenWeather || (response.statusCode !== 200 && response.statusCode !== 201) ) {
                    connection.release();
                    callback({"err": errOpenWeather });
                }
                let meteo = JSON.parse(body).main;
                meteo.date = new Date(event.time*1000);
                meteo.pressure = Math.floor( meteo.pressure );
                console.log('fallback storing data', meteo);
                let query = `INSERT INTO T02_DevicesTransmissions (deviceCode, transmissionDate, temperature, humidity, pressure, unixDate, rawData) VALUES ( ?, ?, ?, ?, ?, ?, ?);`;
                let queryValues = [ event.device, meteo.date, meteo.temp, meteo.humidity, meteo.pressure, event.time, 'fallback']; 
                connection.query( query, queryValues, (errInsert, results, fields) => { 
                    connection.release();
                    console.log('fallback completed with', errInsert ? '' : 'out');
                    if (errInsert) callback({"err": errInsert });
                    else callback();
                });
            });

        });
    });
}

推荐答案

这是一个老问题,但是我花了几个小时来摸索着弄清楚如何正确地进行设置,所以希望别人的时间可以保存:)

如果您的Lambda位于VPC中,则它们需要通过NAT网关才能访问外部服务.

实现此目标的一种方法是:

One way to achieve this is:

  • 将lambda配置为使用一个(或多个)特定子网(Lambda控制台将建议您将不同可用性区域中的至少2个子网与lambda关联,以确保可用性)
  • 不同子网中创建NAT网关
  • 具有与lambda子网关联的路由表,将所有出站流量(0.0.0.0/0)发送到您创建的NAT网关(您可以通过在target字段中选择NAT来做到这一点)
  • 在NAT子网中具有路由表,将所有出站流量发送到Internet网关
  • configure your lambda to use a (or multiple) specific subnets (the Lambda console will suggest you associate at least 2 subnets in different availability zones to your lambda to ensure availability)
  • create a NAT Gateway in a different subnet
  • have the route table associated with your lambda's subnets send all outbound traffic (0.0.0.0/0) to the NAT Gateway you created (you do that by choosing the NAT in the target field)
  • have the route table in the NAT's subnet send all outbound traffic to an Internet Gateway

这将通过NAT和Internet网关正确地路由来自您的lambda的流量,以便它们可以访问外部服务.

This will route traffic from your lambdas properly through the NAT and Internet Gateway so they can reach external services.

请注意,如果您还使用Lambda中的RDS并且打算从外部连接到RDS(例如,从本地计算机管理DB),则不能将RDS实例放入Lambda的子网中,否则您将无法从外部连接到它(仅NAT出站).在这种情况下,您应该确保RDS实例与可访问的子网相关联,例如NAT所在的子网(即向Internet网关发送出站流量的子网).

Note that if you're also using RDS from your lambdas AND you intend to also connect to RDS from outside (e.g. to manage the DB from your local machine), you can't put the RDS instance in the lambdas' subnet, or you won't be able to connect to it from outside (the NAT is outbound only). In that case you should make sure your RDS instance is associated with a subnet that is accessible, for instance the one the NAT is in (i.e. the one that sends outbound traffic to the Internet Gateway).

这篇关于如何在AWS Lambda函数中进行外部api调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆