首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AWS Lambda - MongoDB资源优化

AWS Lambda - MongoDB资源优化
EN

Stack Overflow用户
提问于 2018-06-11 23:39:45
回答 1查看 73关注 0票数 0

我正在使用AWS Lambda和MongoDB构建facebook聊天机器人。目前,我的应用程序非常简单,但在进入复杂的内容之前,我正在尝试确定基础知识。

我知道AWS Lambda是无状态的,但我已经阅读了在处理程序中添加以下行以及在处理程序外部初始化的变量,我不必在每个请求上建立数据库连接。

代码语言:javascript
复制
context.callbackWaitsForEmptyEventLoop = false;

(我从这篇文章中读到了这篇文章;https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs)

我将把我的全部代码添加到下面

代码语言:javascript
复制
'use strict'

const
axios = require('axios'),
mongo = require('mongodb'),
MongoClient = mongo.MongoClient,
assert = require('assert');

var VERIFY_TOKEN = process.env.VERIFY_TOKEN;
var PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
var MONGO_DB_URI = process.env.MONGO_DB_URI;
let cachedDb = null;
let test = null;

exports.handler = (event, context, callback) => {
var method = event.context["http-method"];
context.callbackWaitsForEmptyEventLoop = false;
console.log("test :: " + test);
if (!test) {
    test = "1";
}

// process GET request --> verify facebook webhook
if (method === "GET") {
    var queryParams = event.params.querystring;
    var rVerifyToken = queryParams['hub.verify_token']
    if (rVerifyToken === VERIFY_TOKEN) {
        var challenge = queryParams['hub.challenge'];
        callback(null, parseInt(challenge))
    } else {
        var response = {
            'body': 'Error, wrong validation token',
            'statusCode': 403
        };
        callback(null, response);
    }
    // process POST request --> handle message
} else if (method === "POST") {
    let body = event['body-json'];

    body.entry.map((entry) => {
        entry.messaging.map((event) => {
            if (event.message) {
                if (!event.message.is_echo && event.message.text) {
                    console.log("BODY\n" + JSON.stringify(body));
                    console.log("<<MESSAGE EVENT>>");
                    // retrieve message
                    let response = {
                            "text": "This is from webhook response for \'" + event.message.text + "\'"
                        }
                        // facebook call
                    callSendAPI(event.sender.id, response);

                    // store in DB
                    console.time("dbsave");
                    storeInMongoDB(event, callback);
                }
            } else if (event.postback) {
                console.log("<<POSTBACK EVENT>>");
            } else {
                console.log("UNHANDLED EVENT; " + JSON.stringify(event));
            }

        })
    })
}
}

function callSendAPI(senderPsid, response) {
    console.log("call to FB");
    let payload = {
        recipient: {
            id: senderPsid
        },
        message: response
    };
    let url = `https://graph.facebook.com/v2.6/me/messages?access_token=${PAGE_ACCESS_TOKEN}`;
    axios.post(url, payload)
        .then((response) => {
            console.log("response ::: " + response);
        }).catch(function(error) {
            console.log(error);
        });
}

function storeInMongoDB(messageEnvelope, callback) {
    console.log("cachedDB :: " + cachedDb);
    if (cachedDb && cachedDb.serverConfig.isConnected()) {
        sendToAtlas(cachedDb.db("test"), messageEnvelope, callback);
    } else {
        console.log(`=> connecting to database ${MONGO_DB_URI}`);
        MongoClient.connect(MONGO_DB_URI, function(err, db) {
            assert.equal(null, err);
            cachedDb = db;
            sendToAtlas(db.db("test"), messageEnvelope, callback);
        });
    }
}

function sendToAtlas(db, message, callback) {
    console.log("send to Mongo");
    db.collection("chat_records").insertOne({
        facebook: {
            messageEnvelope: message
        }
    }, function(err, result) {
        if (err != null) {
            console.error("an error occurred in sendToAtlas", err);
            callback(null, JSON.stringify(err));
        } else {
            console.timeEnd("dbsave");
            var message = `Inserted a message into Atlas with id: ${result.insertedId}`;
            console.log(message);
            callback(null, message);
        }
    });
}

我按照指示做了所有事情,并参考了更多类似的案例,但不知何故,每次请求时,"cachedDb“值都不会从上一个请求中保存下来,应用程序会重新建立连接。

然后我还读到,不能保证Lambda函数在多个请求上使用相同的容器,因此我创建了另一个全局变量"test“。来自第二个请求的"test“变量值被记录为"1”,这意味着它正在使用相同的容器,但同样,"cachedDb“值没有被保存。

这里我漏掉了什么?

提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2018-06-11 23:51:28

简而言之,AWS Lambda函数不是任何类型的永久运行的服务。

到目前为止,我知道AWS Lambda在idea上工作--“一个容器一次处理一个请求”。

这意味着当请求到来并且Lambda函数有可用的运行容器时,AWS会使用它,否则它会启动新的容器。

如果在第一个容器对第一个请求执行Lambda函数时出现第二个请求,AWS将启动新的容器。以此类推。

那么不能保证将在哪个容器(已经运行或新的)中执行Lambda函数,所以...新建容器打开新的DB连接。

当然,有一段不活动的时间,在此之后将不会有运行的容器。所有这些都将在下一次请求时重新开始。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50801465

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档