Можно ли перехватить сигналы уничтожения для закрытия соединений с БД непосредственно перед тем, как лямбда-функция будет уничтожена и запущена? - PullRequest
9 голосов
/ 07 мая 2019

Чтобы ускорить выполнение Lambda, я пытаюсь переместить некоторые части моего кода Python за пределы функции-обработчика

Согласно Документация Lambda :

После выполнения лямбда-функции AWS Lambda поддерживает Контекст выполнения в течение некоторого времени в ожидании другой лямбды вызов функции. По сути, служба замораживает выполнение Контекст после завершения лямбда-функции и оттаивания контекста для повторное использование, если AWS Lambda выбирает повторное использование контекста, когда Lambda функция вызывается снова. Этот подход повторного использования контекста выполнения имеет следующие последствия:

Любые объявления в вашей лямбда-функции. код (вне кода обработчика, см. Модель программирования) остается инициализируется, обеспечивая дополнительную оптимизацию, когда функция вызывается снова. Например, если ваша лямбда-функция устанавливает соединение с базой данных, вместо того, чтобы восстановить соединение, исходное соединение используется в последующих вызовах…

Следуя их примеру, я переместил свою логику соединения с базой данных за пределы функции-обработчика, поэтому при последующих WARM выполнении функции можно повторно использовать соединение вместо создания нового при каждом выполнении функции.

Однако AWS Lambda не дает никаких гарантий, что все последующие вызовы функции, которая запустилась COLD , будут прогреваться, поэтому, если Lambda решит, что COLD запуск необходим, мой код будет повторно создать соединение с базой данных.

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

Есть ли в Python способ определить, пытается ли Lambda уничтожить мой экземпляр функции (может быть, они отправляют сигнал SIGTERM?) И закрыть ли она активные подключения к БД?

Я использую базу данных Postgres.

Ответы [ 4 ]

7 голосов
/ 10 мая 2019

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

Учитывая это, холодные ботинки и соединения с БД - очень обсуждаемые темы, использующие Lambdas. Хуже всего то, что нет однозначного ответа, и его следует рассматривать на основе варианта использования.

Лично я думаю, что лучший способ сделать это - создать соединения и убить свободные, основываясь на тайм-ауте postgres. Для этого я направляю вас на Как автоматически закрывать незанятые соединения в PostgreSQL?

Возможно, вы также захотите настроить количество лямбд у вас в любой момент времени. Для этого я бы порекомендовал установить уровень параллелизма в вашей лямбде aws-docs . Таким образом, вы ограничиваете количество запускаемых лямбд и, возможно, не затопляете свой сервер БД соединениями.

У Джереми Дейли (герой без сервера) есть отличная запись в блоге на эту тему. Как: управлять RDS-соединениями из функций AWS Lambda без сервера

У него также есть проект, к сожалению, в узле, который является оболочкой для соединения mysql. Это контролирует соединение и автоматически управляет ими как убийство зомби serverless-mysql . Вы можете найти что-то похожее на Python.

3 голосов
/ 13 мая 2019

Я не думаю, что то, что вы ищете, возможно в данный момент.Хаки могут работать, но я не советую зависеть от них, поскольку недокументированные вещи могут перестать работать в любой момент времени без уведомления в системе с закрытым исходным кодом.

Я полагаю, вас беспокоит количество новых соединений, созданныхваши лямбда-функции и нагрузка, которую он создает на сервер базы данных.

Вы видели pgbouncer (https://pgbouncer.github.io/) это один из известных пулеров соединений для postgres. Я бы рекомендовал использовать что-то вроде pgbouncer междуваша лямбда-функция и db.

Это снимет нагрузку на ваш db-сервер, вызванную созданием нового соединения, так как соединения между pgbouncer и postgres могут оставаться в течение длительного времени. Лямбда-функции могут устанавливать новое соединение с pgbouncer, котороеболее чем способен обрабатывать незамкнутые соединения с различными настройками конфигурации тайм-аута.

0 голосов
/ 12 мая 2019

У меня нет времени, чтобы проверить это, но как насчет trap - Я сейчас в АФК, но когда я войду, я отредактирую этот ответ после некоторых экспериментов?

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

В вашем обработчике вы добавили бы команду оболочки, которая запускает этот скрипт, а затем установили переменную, которая будет оставаться на месте, пока контейнер используется повторно - я не питон, но ваша логика могла бы что-то сделать как это:

Обработчик

const { exec } = require('child_process');

if(typeof isNewContainer === 'undefined'){
     const isNewContainer = true 

    // run a shell script, in javascript we use shell exec and 
    // then have a callback for when it exits so the execution is non blocking and allows 
    // the code below to execute.
    exec('./script.sh & sleep 1 && kill -- -$(pgrep script.sh)', (err, stdout, stderr) => {
    // close db connections
   }


}

// handle the request

Сценарий оболочки на основе этого ответа:

#!/bin/bash
exitCallback() {
    trap - SIGTERM # clear the trap
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

trap exitCallback SIGTERM

sleep infinity

Убедитесь, что вы прочитали комментарии к принятому ответу на этот вопрос, поскольку он дает вам команды оболочки для запуска сценария.

Я бы сказал, что поддерживать контейнеры в тепле довольно просто, но ваш вопрос был таков: "Есть ли в Python способ определить, пытается ли Lambda уничтожить мой экземпляр функции (возможно, они посылают сигнал SIGTERM?) И закрыть ли он активную базу данных?" соединения? "

0 голосов
/ 11 мая 2019

Я полностью согласен с @ dudemullet.

В настоящее время нет никакого способа точно сказать, когда лямбда-функция умрет.Лучший подход - сначала понять цель вашей связи.Если это всего лишь простой запрос выбора / обновления, который в идеале не должен занимать слишком много времени, я бы предложил вам открыть и закрыть соединения внутри функции-обработчика.Таким образом, по крайней мере, вы можете быть на 100% уверены, что не будет никаких потерянных соединений

Но, с другой стороны, вам, возможно, придется потерять несколько лишних миллисекунд холодного запуска!

...