如何在 AWS Lambda 函数中进行外部 api 调用
How to make an external api call within an AWS Lambda function
我遇到 Lambda 函数 的问题,由于某种原因 超时 .
我尝试添加一些 console.log 以了解发生了什么,一切正常,直到外部 http 请求。
我使用 npm 模块请求
我可以看到请求之前的日志,但回调中的日志从未出现,就像端点没有响应一样。
我错过了什么吗?提前致谢!
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();
});
});
});
});
}
您没有设置 VPC,对吧?如果这样做,如果您在私有子网上,则必须检查您是否连接了 NAT 网关。
这是您的解决方案,请阅读。
进一步
此代码示例展示了如何在您的技能 Lambda 代码中调用和接收外部休息服务数据。
https://github.com/robm26/SkillsDataAccess/blob/master/src/CallService/index.js
这是一个老问题,但我花了几个小时思考如何正确设置它,所以希望能节省其他人的时间:)
如果您的 lambda 位于 VPC 中,它们需要通过 NAT 网关才能访问外部服务。
实现此目的的一种方法是:
- 将您的 lambda 配置为使用一个(或多个)特定子网(Lambda 控制台将建议您将不同可用性区域中的至少 2 个子网关联到您的 lambda 以确保可用性)
- 在不同 子网
中创建 NAT 网关
- 让与您的 lambda 子网关联的路由 table 将所有出站流量 (0.0.0.0/0) 发送到您创建的 NAT 网关(您可以通过在
target
中选择 NAT 来实现)场)
- 让 NAT 子网中的路由 table 将所有出站流量发送到 Internet 网关
这将通过 NAT 和 Internet 网关正确路由来自您的 lambda 的流量,以便它们可以访问外部服务。
请注意,如果您还使用 lambda 中的 RDS 并且您还打算从外部连接到 RDS(例如,从本地计算机管理数据库),则不能将 RDS 实例放入 lambda 中' 子网,否则您将无法从外部连接到它(NAT 仅用于出站)。在这种情况下,您应该确保您的 RDS 实例与可访问的子网相关联,例如 NAT 所在的子网(即向 Internet 网关发送出站流量的子网)。
我遇到 Lambda 函数 的问题,由于某种原因 超时 .
我尝试添加一些 console.log 以了解发生了什么,一切正常,直到外部 http 请求。
我使用 npm 模块请求
我可以看到请求之前的日志,但回调中的日志从未出现,就像端点没有响应一样。
我错过了什么吗?提前致谢!
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();
});
});
});
});
}
您没有设置 VPC,对吧?如果这样做,如果您在私有子网上,则必须检查您是否连接了 NAT 网关。
这是您的解决方案,请阅读。
进一步
此代码示例展示了如何在您的技能 Lambda 代码中调用和接收外部休息服务数据。 https://github.com/robm26/SkillsDataAccess/blob/master/src/CallService/index.js
这是一个老问题,但我花了几个小时思考如何正确设置它,所以希望能节省其他人的时间:)
如果您的 lambda 位于 VPC 中,它们需要通过 NAT 网关才能访问外部服务。
实现此目的的一种方法是:
- 将您的 lambda 配置为使用一个(或多个)特定子网(Lambda 控制台将建议您将不同可用性区域中的至少 2 个子网关联到您的 lambda 以确保可用性)
- 在不同 子网 中创建 NAT 网关
- 让与您的 lambda 子网关联的路由 table 将所有出站流量 (0.0.0.0/0) 发送到您创建的 NAT 网关(您可以通过在
target
中选择 NAT 来实现)场) - 让 NAT 子网中的路由 table 将所有出站流量发送到 Internet 网关
这将通过 NAT 和 Internet 网关正确路由来自您的 lambda 的流量,以便它们可以访问外部服务。
请注意,如果您还使用 lambda 中的 RDS 并且您还打算从外部连接到 RDS(例如,从本地计算机管理数据库),则不能将 RDS 实例放入 lambda 中' 子网,否则您将无法从外部连接到它(NAT 仅用于出站)。在这种情况下,您应该确保您的 RDS 实例与可访问的子网相关联,例如 NAT 所在的子网(即向 Internet 网关发送出站流量的子网)。