2

したがって、ラムダ関数を最適化するために、https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejsの例に従っています。

私は2つのアプローチを試し、ローカルでテストしましたがserverless-offline、どちらもうまくいかないようです。

最初のアプローチ

// endpoint file

import {connectToDatabase} from "lib/dbUtils.js";

let cachedDb = null;

export function post(event, context, callback) {
  let response;
  context.callbackWaitsForEmptyEventLoop = false;
  connectToDatabase()
    .then(//do other stuff

// lib/dbUtils.js

export async function connectToDatabase() {
  if (cachedDb && cachedDb.serverConfig.isConnected()) {
    console.log(" using cached db instance");
    return cachedDb;
  }
  cachedDb = await mongoose.createConnection(
    process.env.DB_URL,
    async err => {
      if (err) {
        throw err;
      }
    }
  );
  return cachedDb;
}

第二のアプローチ

global.cachedDb = null;

export function post(event, context, callback) {
  let response;
  context.callbackWaitsForEmptyEventLoop = false;
  connectToDatabase()
    .then(connection => createUser(event.body, connection))


// lib/dbUtils.js

export async function connectToDatabase() {
  // eslint-disable-next-line
  if (global.cachedDb && global.cachedDb.serverConfig.isConnected()) {
    // eslint-disable-next-line
    console.log(" using cached db instance");
    // eslint-disable-next-line
    return global.cachedDb;
  }
  // eslint-disable-next-line
  global.cachedDb = await mongoose.createConnection(
    process.env.DB_URL,
    async err => {
      if (err) {
        throw err;
      }
    }
  );
  // eslint-disable-next-line
  return global.cachedDb;
}

どちらの場合も、using cached db instanceコンソール ログは実行されません。

これが機能しないのはなぜですか?これはサーバーレス オフラインが原因ですか?

4

1 に答える 1

2

答えは簡単ですserverless-offline。完全な AWS をシミュレートするわけではありません。AWS コンソールを使用して実際の Lambda を作成する

MongoDB Atlas ガイドは問題ありませんが、各ラムダのオプションを説明している公式のAWS Lambda ドキュメントも確認する価値があります。context

callbackWaitsForEmptyEventLoop– Node.js イベント ループが空になるのを待つのではなく、コールバックの実行時にすぐに応答を送信するには、false に設定します。false の場合、未処理のイベントは次の呼び出し時に引き続き実行されます。

実際の Lambda でコードを実行using cached db instanceし、コンソールで確認することができます。MongoDB の JavaScript コードはかなり貧弱なので、以下に独自のバージョンを書きました。

var MongoClient = require("mongodb").MongoClient

let db = null

var log = console.log.bind(console)

var print = function(object) {
    return JSON.stringify(object, null, 2)
}

// Use your own credentials (and better yet, put them in environment variables)
const password = `notactuallyapassword`
const uri = `mongodb+srv://lambdauser:${password}@fakedomain.mongodb.net/test?retryWrites=true`

exports.handler = function(event, context, callback) {
    log(`Calling MongoDB Atlas from AWS Lambda with event: ${print(event)}`)
    var document = JSON.parse(JSON.stringify(event))

    const databaseName = "myDatabase",
        collectionName = "documents"

    // See https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs
    // and https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html#nodejs-prog-model-context-properties
    context.callbackWaitsForEmptyEventLoop = false

    return createDoc(databaseName, collectionName, document)
}

async function createDoc(databaseName, collectionName, document) {
    var isConnected = db && db.serverConfig.isConnected()
    if (isConnected) {
        log(`Already connected to database, warm start!`)
    } else {
        log(`Connecting to database (cold start)`)
        var client = await MongoClient.connect(uri)
        db = client.db(databaseName)
    }

    var result = await db.collection(collectionName).insertOne(document)
    log(`just created an entry into the ${collectionName} collection with id: ${result.insertedId}`)
    // Don't close the connection thanks to context.callbackWaitsForEmptyEventLoop = false - this will re-use the connection on the next called (if it can re-use the same Lambda container)
    return result
}

[テスト] ボタンを使用して、AWS Lambda コンソールで上記のラムダを2 回実行します。

  • 初めて実行するとわかりますConnecting to database (cold start)

  • 見るのは二回目Already connected to database, warm start!

以下のスクリーンショットのログ出力セクションを参照してください。

ここに画像の説明を入力

于 2019-04-08T09:03:25.350 に答える