it-swarm.com.ru

MongoDB соединения от AWS Lambda

Я пытаюсь создать RESTful API с помощью AWS Lambda/API Gateway, подключенного к базе данных MongoDB. Я читал, что соединения с MongoDB относительно дороги, поэтому рекомендуется сохранять соединение для повторного использования после его установления, а не создавать новые соединения для каждого нового запроса.

Это довольно просто для обычных приложений, так как вы можете установить соединение во время запуска и повторно использовать его в течение срока службы приложений. Но, поскольку лямбда предназначена для сохранения состояния без сохранения состояния, эта связь кажется менее прямой.

Поэтому мне интересно, как лучше всего подойти к этой проблеме с подключением к базе данных? Я вынужден устанавливать новые соединения каждый раз, когда вызывается лямбда-функция, или есть способ объединить/кэшировать эти соединения для более эффективных запросов?

Благодарю.

47
Beesknees

Лямбда-функции AWS должны быть определены как функции без сохранения состояния, поэтому они не могут хранить состояние, как пул соединений.

Этот вопрос также поднимался в этом сообщении на форуме AWS . 5 октября 2015 года инженер AWS Шон объявил, что вы должны не открывать и закрывать соединение по каждому запросу, создавая пул при инициализации кода вне блока обработчика. Но через два дня тот же инженер написал, что вы не должны этого делать.

Проблема в том, что вы не можете контролировать среду выполнения Lambda. Мы знаем, что эти среды (или контейнеры) используются повторно, как описано в блоге Тима Вагнера . Но отсутствие контроля может вынудить вас истощить все свои ресурсы, например, достичь лимита подключения в вашей базе данных. Но это зависит от вас.

Вместо подключения к MongoDB из вашей лямбда-функции вы можете использовать RESTHeart для доступа к базе данных через HTTP. Вместо этого пул соединений с MongoDB поддерживается RESTHeart. Помните, что в отношении производительности вы будете открывать новое HTTP-соединение с RESTHeart при каждом запросе, а не использовать пул HTTP-соединений, как вы могли бы сделать в традиционном приложении.

13
tuler

Restheart - это сервер на основе REST, который работает вместе с MongoDB. Он отображает большинство операций CRUD в Mongo на GET, POST и т.д., Запросы с расширяемой поддержкой, когда вам нужно написать собственный обработчик (например, специализированный geoNear, запрос geoSearch)

5
user1694845

Вы должны предполагать, что лямбды не имеют состояния, но реальность такова, что большую часть времени виртуальная машина просто заморожена и делает поддерживает some состояние. Для Amazon было бы глупо запускать новый процесс для каждого запроса, поэтому они часто используют один и тот же процесс, и вы можете воспользоваться этим, чтобы избежать разрыва соединений.

Чтобы избежать подключения для каждого запроса (в случаях, когда лямбда-процесс используется повторно):

  1. Напишите обработчик, предполагая, что процесс используется повторно, так что вы подключаетесь к базе данных и заставляете lamba повторно использовать пул соединений (обещание db, возвращаемое из MongoClient.connect).

  2. Чтобы лямбда не зависала, ожидая, пока вы закроете соединение с БД, db.close(), после обслуживания запроса, скажите, что он не ожидает пустой цикл обработки событий.

Пример:

var db = MongoClient.connect(MongoURI);

module.exports.targetingSpec = (event, context, callback) => {
  context.callbackWaitsForEmptyEventLoop = false;
  db.then((db) => {
    // use db
  });
};

Из документации о context.callbackWaitsForEmptyEventLoop:

callbackWaitsForEmptyEventLoop Значение по умолчанию верно. Это свойство полезно только для изменения поведения обратного вызова по умолчанию. По умолчанию обратный вызов будет ожидать, пока цикл событий времени выполнения Node.js не станет пустым, прежде чем заморозить процесс и вернуть результаты вызывающей стороне. Можно установить для этого свойства значение false, чтобы запросить AWS Lambda заморозить процесс вскоре после вызова обратного вызова, даже если в цикле событий есть события. AWS Lambda заморозит процесс, любые данные о состоянии и события в цикле событий Node.js (любые оставшиеся события в цикле событий обрабатываются при следующем вызове функции Lambda и если AWS Lambda решает использовать замороженный процесс). Для получения дополнительной информации об обратном вызове см. Использование параметра обратного вызова.

3
Tyler Brock

Я провел несколько тестов, выполняющих функции Java Lambda, подключающиеся к MongoDB Atlas.

Как уже указывалось другими авторами, Amazon повторно использует Экземпляры, однако они могут быть переработаны, и точное поведение не может быть определено. Таким образом, можно получить устаревшие связи. Я собираю данные каждые 5 минут и отправляю их в функцию Lambda каждые 5 минут.

Лямбда в основном делает:

  • Создание или повторное использование соединения
  • Запросить одну запись
  • Написать или обновить одну запись
  • закрыть соединение или оставить его открытым

Фактический объем данных довольно низок. В зависимости от времени суток оно варьируется от 1 до 5 кБ. Я использовал только 128 МБ.

Lambdas бежал в N.Virgina, поскольку это место, где свободный уровень связан с.

При открытии и закрытии соединения каждый раз большинство вызовов занимает от 4500 до 9000 мс. При повторном использовании соединения большинство вызовов составляет от 300 до 900 мс. При проверке консоли Atlas количество соединений остается стабильным. В этом случае повторное использование соединения того стоит. Создание соединения и даже отключение от набора реплик довольно дорого с использованием драйвера Java.

Для крупномасштабного развертывания необходимо выполнить более комплексные тесты.

2
Udo Held

Короткий ответ: да, вам нужно создать новое соединение и закрыть его до окончания лямбда-выражения.

Длинный ответ на самом деле во время моих тестов, вы можете передать ваши соединения с БД в вашем обработчике, вот так (пример mysql, это то, что я имею в виду), вы не можете полагаться на это, имея соединение, поэтому проверьте мой пример ниже, может случиться так, что после того, как ваши лямбды не выполнялись целую вечность, они теряли состояние из обработчика (холодный старт), мне нужно сделать больше тестов, чтобы выяснить это, но я заметил, получает ли лямбда много трафика используя приведенный ниже пример, он не создает новое соединение.

// MySQL.database.js
    import * as mysql from 'mysql'

    export default mysql.createConnection({
        Host: 'mysql db instance address',
        user: 'MYSQL_USER',
        password: 'PASSWORD',
        database: 'SOMEDB',
    })

Затем в ваш обработчик импортируйте его и передайте его в лямбду, которая выполняется.

// handler.js
import MySQL from './MySQL.database.js'

const funcHandler = (func) => {
    return (event, context, callback) => {
        func(event, context, callback, MySQL)
    }
}

const handler = {
    someHandler: funcHandler(someHandler),
}

export default handler

Теперь в вашей лямбде вы делаете ...

export default (event, context, callback, MySQL) => {
  context.callbackWaitsForEmptyEventLoop = false
  // Check if their is a MySQL connection if not, then open one.

 // Do ya thing, query away etc etc

  callback(null, responder.success()) 


}

Пример респондента может он нашел здесь. извините, это ES5, потому что именно там был задан вопрос. 

Надеюсь это поможет!

0
Mrk Fldig

К сожалению, вам может потребоваться создать собственный API RESTful для ответа на запросы MongoDB, пока AWS не предложит его. Пока у них есть только то, что вам нужно для их собственной БД Динамо.

0
Marin