Nic*_*las 16 amazon-web-services redis node.js aws-lambda serverless-framework
我正在尝试使用AWS Lambda和无服务器框架为单页面Web应用程序构建API .我想使用Redis Cloud进行存储,主要是因为它结合了速度和数据持久性.我将来可能会使用更多的Redis Cloud功能,所以我宁愿避免使用ElastiCache.我的Redis Cloud实例与我的函数在同一AWS区域中运行.
我有一个函数调用related,它从GET请求到API端点获取一个hashtag,并检查数据库中是否有一个条目.如果它在那里,它应该立即返回结果.如果没有,它应该查询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)
}
})
}
Run Code Online (Sandbox Code Playgroud)
这是../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)
}
})
}
})
}
}
})
})
}
Run Code Online (Sandbox Code Playgroud)
所有这些都按预期工作到了一定程度.如果我在本地(使用sls function run related)运行该函数,我没有任何问题 - 标记从Redis数据库读取和写入应该是.但是,当我部署它(使用sls dash deploy)时,它在部署后第一次运行时工作,然后停止工作.所有后续尝试运行它只是返回null浏览器(或邮递员,或卷曲,或Web应用程序).无论我用于测试的标签是否已经存在于数据库中,都是如此.如果我然后重新部署,不对函数本身进行任何更改,它再次工作一次.
在我的本地计算机上,该函数首先登录Connected: true到控制台,然后是查询结果,然后Connection closed.在AWS上,它会记录Connected: true,然后是查询结果,就是这样.在第二次运行时,它记录Connection closed.,没有别的.在第三次和所有后续运行中,它根本不记录任何内容.这两种环境都没有报告任何错误.
似乎很清楚,问题在于与Redis的连接.如果我没有在回调中关闭它,那么后续尝试调用该函数只是超时.我也试过用redis.unref而不是redis.quit,但这似乎没有任何区别.
任何帮助将不胜感激.
Nic*_*las 23
我现在已经解决了自己的问题,希望将来可以帮助遇到这个问题的人.
连接到数据库时有两个主要注意事项,就像我在上面的代码中从Lambda函数中所做的那样:
context.succeed(),context.fail()或被context.done()调用,AWS可能会冻结尚未完成的任何进程.这是导致AWS登录Connection closed到我的API端点的第二次调用的原因 - 该过程在Redis完成关闭之前被冻结,然后在下一次调用时解冻,此时它继续向右停止,报告连接是关闭.要点:如果要关闭数据库连接,请确保在调用其中一种方法之前将其完全关闭.您可以通过在由连接关闭(.on('end')在我的情况下)触发的事件处理程序中放置回调来完成此操作.require并将它们放在每个文件的顶部,就像我一样,亚马逊会尽可能多地在内存中缓存这些模块.如果这导致问题,请尝试require()在函数内而不是在文件顶部移动调用,然后导出该函数.无论何时运行该函数,都将重新导入这些模块.这是我更新的代码.请注意,我还将我的Redis配置放在一个单独的文件中,因此我可以将其导入其他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)
}
})
}
Run Code Online (Sandbox Code Playgroud)
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))
}
Run Code Online (Sandbox Code Playgroud)
'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
})
}
})
}
})
}
}
})
})
}
Run Code Online (Sandbox Code Playgroud)
这完全按照应有的方式工作 - 而且速度也很快.
| 归档时间: |
|
| 查看次数: |
16128 次 |
| 最近记录: |