我应该如何从AWS Lambda函数连接到Redis实例?

我正在尝试使用AWS Lambda和无服务器框架为单页Web应用程序构buildAPI。 我希望使用Redis Cloud进行存储,主要是为了兼顾速度和数据持久性。 我将来可能会使用更多的Redis Cloudfunction,所以我宁愿避免使用ElastiCache。 我的Redis Cloud实例与我的function在同一AWS区域中运行。

我有一个名为related的函数,它将GET请求中的hashtag接收到API端点,并检查数据库中是否有条目。 如果它在那里,它应该立即返回结果。 如果不是,则应查询RiteTag ,将结果写入Redis,然后将结果返回给用户。

我很新,所以我可能做一些天真的事情。 这是事件处理程序:

 'use strict' const lib = require('../lib/related') module.exports.handler = function (event, context) { lib.respond(event, (err, res) => { if (err) { return context.fail(err) } else { return context.succeed(res) } }) } 

这是../lib/related.js文件:

 var redis = require('redis') var jsonify = require('redis-jsonify') var rt = require('./ritetag') var redisOptions = { host: process.env.REDIS_URL, port: process.env.REDIS_PORT, password: process.env.REDIS_PASS } var client = jsonify(redis.createClient(redisOptions)) module.exports.respond = function (event, callback) { var tag = event.hashtag.replace(/^#/, '') var key = 'related:' + tag client.on('connect', () => { console.log('Connected:', client.connected) }) client.on('end', () => { console.log('Connection closed.') }) client.on('ready', function () { client.get(key, (err, res) => { if (err) { client.quit() callback(err) } else { if (res) { // Tag is found in Redis, so send results directly. client.quit() callback(null, res) } else { // Tag is not yet in Redis, so query Ritetag. rt.hashtagDirectory(tag, (err, res) => { if (err) { client.quit() callback(err) } else { client.set(key, res, (err) => { if (err) { callback(err) } else { client.quit() callback(null, res) } }) } }) } } }) }) } 

所有这一切都按预期工作,至关重要。 如果我在本地运行该function(使用sls function run related ),我没有任何问题 – 标签读取和写入到Redis数据库应该是。 但是,当我部署它(使用sls dash deploy )时,它在部署后第一次运行 ,然后停止工作。 所有后续尝试运行它只是简单地将null返回给浏览器(或Postman,Curl或Web应用程序)。 无论我用于testing的标签是否已经在数据库中,情况都是如此。 如果我再重新部署,不改变function本身,它再次工作 – 一次。

在我的本地机器上,函数首先在控制台上loggingConnected: true ,然后查询结果,然后Connection closed. 在AWS上,它会loggingConnected: true ,然后是查询结果,就是这样。 在第二次运行时,它loggingConnection closed. 没有别的。 在第三次和所有后续的运行中,它什么都不logging。 任何环境都不会报告任何错误。

这似乎很明显,问题是与Redis的连接。 如果我不在callback中closures它,那么随后尝试调用该函数就会超时。 我也尝试使用redis.unref而不是redis.quit ,但这似乎没有任何区别。

任何帮助将不胜感激。

现在我已经解决了自己的问题,希望将来能够帮助遇到这个问题的人。

连接到数据库时有两个主要考虑因素,就像我在上面的代码中从Lambda函数中所做的那样:

  1. 一旦调用了context.succeed()context.fail()context.done() ,AWS可以冻结尚未完成的任何进程。 这就是导致AWS在第二次调用API时Connection closed的原因 – 在Redis完成closures之前,进程被冻结,然后在下次调用时解冻,此时它继续从停止的地方继续,报告连接被closures。 外卖:如果你想closures你的数据库连接, 你调用这些方法之前 ,确保它完全closures。 你可以通过在连接close( .on('end')触发的事件处理程序中进行callback来做到这一点)。
  2. 如果将代码分割成单独的文件,并require它们位于每个文件的顶部,就像我一样,Amazon将尽可能多地在内存中caching这些模块。 如果这导致了问题,请尝试在函数内移动require()调用,而不是在文件顶部,然后导出该函数。 这些模块将在运行时重新导入。

这是我更新的代码。 请注意,我也已将我的Redisconfiguration放入单独的文件,因此我可以将其导入其他Lambda函数而不重复代码。

事件处理程序

 'use strict' const lib = require('../lib/related') module.exports.handler = function (event, context) { lib.respond(event, (err, res) => { if (err) { return context.fail(err) } else { return context.succeed(res) } }) } 

Redisconfiguration

 module.exports = () => { const redis = require('redis') const jsonify = require('redis-jsonify') const redisOptions = { host: process.env.REDIS_URL, port: process.env.REDIS_PORT, password: process.env.REDIS_PASS } return jsonify(redis.createClient(redisOptions)) } 

function

 'use strict' const rt = require('./ritetag') module.exports.respond = function (event, callback) { const redis = require('./redis')() const tag = event.hashtag.replace(/^#/, '') const key = 'related:' + tag let error, response redis.on('end', () => { callback(error, response) }) redis.on('ready', function () { redis.get(key, (err, res) => { if (err) { redis.quit(() => { error = err }) } else { if (res) { // Tag is found in Redis, so send results directly. redis.quit(() => { response = res }) } else { // Tag is not yet in Redis, so query Ritetag. rt.hashtagDirectory(tag, (err, res) => { if (err) { redis.quit(() => { error = err }) } else { redis.set(key, res, (err) => { if (err) { redis.quit(() => { error = err }) } else { redis.quit(() => { response = res }) } }) } }) } } }) }) } 

这完全按照它应该的方式工作,而且它的速度也非常快。