我正在尝试编写一个缓存函数,返回缓存的elasticcache数据或使api调用检索该数据。然而,lambda函数似乎非常不可靠,并且经常超时。
似乎这个问题是有redis调用以及公共api调用导致的问题。我可以确认我已经正确地设置了带有互联网网关的子网和带有nat网关的私有子网的aws。这个功能有效,但只有10%的时间有效。其余时间在调用API之前停止执行。我也注意到,api调用失败后创建redis客户端。如果我在进行redis检查之前进行外部api调用,似乎该功能更可靠,不会超时。
不知道该怎么做。最好的做法是把这两个任务分开,还是我做错了什么?
let data = null;
module.exports.handler = async (event) => {
//context.callbackWaitsForEmptyEventLoop = false;
let client;
try {
client = new Redis(
6379,
"redis://---.---.ng.0001.use1.cache.amazonaws.com"
);
client.get(event.token, async (err, result) => {
if (err) {
console.error(err);
} else {
data = result;
await client.quit();
}
});
if (data && new Date().getTime() / 1000 - eval(data).timestamp < 30) {
res.send(`({
"address": "${token}",
"price": "${eval(data).price}",
"timestamp": "${eval(data).timestamp}"
})`);
} else {
getPrice(event); //fetch api data
}
```
你的代码中有很多误解。我将试着指导你修复它,并了解如何正确地做到这一点。
- 你在函数中混合了异步和同步代码。 你应该使用JSON。用parse而不是eval来解析数据,因为eval允许在函数中执行任意代码你正在使用res.send来向客户端返回响应,而不是回调。记住,res.send的用法只在express中使用,并且使用lambda,要将结果返回给客户端,需要使用回调函数
为了帮助你完成这项任务,我完全重写了你的代码来解决这些误解。
const Redis = require('ioredis');
module.exports.handler = async (event, context, callback) => {
// prefer to use lambda env instead of put directly in the code
const client = new Redis(
"REDIS_PORT_ENV",
"REDIS_HOST_ENV"
);
const data = await client.get(event.token);
client.quit();
const parsedData = JSON.parse(data);
if (parsedDate && new Date().getTime() / 1000 - parsedData.timestamp < 30) {
callback(null, {
address: event.token,
price: parsedData.price,
timestamp: parsedData.timestamp
});
} else {
const dataFromApi = await getPrice(event);
callback(null, dataFromApi);
}
};
lambda的另一种用法是返回一个对象,而不是在callback中传递一个对象,但我认为你明白了这个想法并理解了你的错误。
按照文档正确使用lambda:https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-lambda-functions.html
要了解更多关于javascript中的async和sync:https://www.freecodecamp.org/news/synchronous-vs-asynchronous-in-javascript/
JSON。解析eval: JSON。Parse与eval()