AWS SQS + API Gateway + Lambda + DB - PullRequest
       23

AWS SQS + API Gateway + Lambda + DB

1 голос
/ 29 марта 2019

Я использую API Gateway + Lambda + DB.

Если много запросов, слишком много подключений. Произошла ошибка.

Для тестирования я не хочу увеличивать опцию максимального количества подключений.

Можно ли использовать SQS -> Lambda -> API Gateway -> Lambda -> DB?

Или другим способом?

Ответы [ 2 ]

2 голосов
/ 29 марта 2019

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

При этом количество подключений к БД будет примерно равным количеству одновременных вызовов.

Вы можете установить предел параллелизма лямбды так, чтобы он ограничивал активные соединения (но это означает, что запуск лямбды может произойти сбой из-за ограничения параллелизма, когда вы достигнете его).

Вы можете запустить свою лямбду с помощью SQS, и при этом запросы будут помещаться в очередь в случае достижения лимита параллелизма до тех пор, пока предыдущие запросы не будут завершены.

Использование SQS без установки ограничения параллелизма для вашей лямбды не решит проблему, потому что количество одновременных вызовов (= активных соединений) все еще может быть высоким.

Я не вижу никакой выгоды, если сделаю что-то вроде 'SQS -> Lambda -> API Gateway -> Lambda -> DB'. Возможный вариант использования: «Шлюз API -> SQS -> Лямбда».

Вы также можете просто использовать «API Gateway -> Lambda» для установки лимита параллелизма лямбды. В этом случае некоторые вызовы к API-шлюзу могут завершиться неудачно, и их следует повторить с экспоненциальным откатом .

0 голосов
/ 29 марта 2019

Можно ли использовать SQS -> Lambda -> API Gateway -> Lambda -> DB?

Ответ: Да, вы можете это сделать, см. Следующий пример, замените ваш вызов наapi getway url и hit rest call, но не решение вашей проблемы.

var https = require('https');
       exports.handler = (event, context, callback) => {
       var params = {
                    host: "bittrex.com",
                    path: "/api/v1.1/public/getmarketsummaries"

                    };

  var req = https.request(params, function(res) {
    let data = '';
    console.log('STATUS: ' + res.statusCode);
    res.setEncoding('utf8');
    res.on('data', function(chunk) {
        data += chunk;
    });
    res.on('end', function() {
        console.log("DONE");
        console.log(JSON.parse(data));
    });
  });
   req.end();
 };

Other Approch:

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

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

Пример:

import sys
import logging
import rds_config
import pymysql
#rds settings
rds_host  = "rds-instance-endpoint"
name = rds_config.db_username
password = rds_config.db_password
db_name = rds_config.db_name

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
    conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
except:
    logger.error("ERROR: Unexpected error: Could not connect to MySQL instance.")
    sys.exit()

logger.info("SUCCESS: Connection to RDS MySQL instance succeeded")
def handler(event, context):
    """
    This function fetches content from MySQL RDS instance
    """

    item_count = 0

    with conn.cursor() as cur:
        cur.execute("create table Employee3 ( EmpID  int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))")  
        cur.execute('insert into Employee3 (EmpID, Name) values(1, "Joe")')
        cur.execute('insert into Employee3 (EmpID, Name) values(2, "Bob")')
        cur.execute('insert into Employee3 (EmpID, Name) values(3, "Mary")')
        conn.commit()
        cur.execute("select * from Employee3")
        for row in cur:
            item_count += 1
            logger.info(row)
            #print(row)
    conn.commit()

    return "Added %d items from RDS MySQL table" %(item_count)

Выполнение pymysql.connect () вне обработчика позволяет вашей функции повторно использовать соединение с базой данных для повышения производительности.

...