Уменьшите задержку DynamoDB от Java Lambda - PullRequest
0 голосов
/ 22 мая 2018

Как я могу уменьшить задержку между Lambda и DynamoDB?

Это лямбда Java, и для выполнения каждой из 2 операций DynamoDB с использованием SDK, поставляемого AWS, требуется 4 секунды.Я слышал, что они обычно завершаются в течение <20 мс, но для меня это на 3 порядка выше.Эти длинные операции: (а) создание объекта DynamoDB и (б) выполнение сканирования таблицы на <em>полностью пустой таблице (код ниже).

Что я должен сделать, чтобы уменьшить задержку?

Вещи, которые я пробовал

  • И лямбда, и DynamoDB находятся в одном регионе (eu-west-1).
  • В таблице 5 RCU &ВКА.Увеличение их не помогает.
  • Максимальный объем памяти, используемый лямбда-памятью, составляет 92 МБ.Если я выделю минимум 128 МБ, то это произойдет через 15 секунд.Увеличение памяти до 512 МБ позволяет достичь времени 4 с на вызов, а увеличение ее до 1 ГБ уменьшает ее до 2 с на вызов.Тем не менее, это абсурдный объем памяти для тривиальной лямбды, и все равно у меня остается> 200x ожидаемая задержка.
  • Метрики таблицы показывают, что время сканирования таблицы составляет от 12 мс до 15 мс.Это то, что я ожидал.Даже с учетом накладных расходов на установление сетевого соединения я все еще ожидаю несколько десятков миллисекунд, а не нескольких секунд.
  • Я запускаю лямбда-функцию, используя функцию тестирования в консоли AWS.Я также пытался запускать через API-шлюз (что я и буду делать в конечном итоге) с теми же результатами.
  • Я пытался вызвать лямбду несколько раз в быстрой последовательности (чтобы уменьшить вероятность того, что ямучаюсь настройкой затрат).Это не помогло.
  • В журнале показано, что все остальные части лямбды работают очень быстро (в миллисекундах).

Фрагменты кода

Создание DynamoDBобъекты

log("Creating AmazonDynamoDB");
AmazonDynamoDB db = AmazonDynamoDBClientBuilder                        
  .standard()
  .withRegion(Regions.EU_WEST_1)
  .build();

log("Creating DynamoDBMapper");
DynamoDBMapper mapper = new DynamoDBMapper(db);

Выполнение сканирования

log("Scanning table");
List<MyItem> items = dbMapper.scan(MyTable.class, new DynamoDBScanExpression());
for (MyItem item : items) {
        // Irrelevant - there aren't any
}
log("Table scan complete");

Примеры журналов

А вот журналы из прогона.

20:07:41 START RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc Version: $LATEST
20:07:41 Received request: APIGatewayRequest(path=/data/foo, httpMethod=POST, body=)
20:07:41 Creating AmazonDynamoDB
20:07:45 Creating DynamoDBMapper
20:07:45 Creating DataHandler
20:07:45 Handling request
20:07:45 Scanning table
20:07:49 Table scan complete
20:07:49 Request handled - response object: []
20:07:49 APIGatewayResponse(isBase64Encoded=false, statusCode=200, body=[], headers={})
20:07:49 END RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc
20:07:49 REPORT RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc Duration: 8256.47 ms Billed Duration: 8300 ms Memory Size: 512 MB Max Memory Used: 85 MB

Ответы [ 3 ]

0 голосов
/ 22 августа 2018

(это не ответ, но я надеюсь, что это поможет кому-то еще) Я сделал обновления, размещенные здесь, и я, кроме них, должен был выполнить "фиктивную" операцию запроса на DynamoDb (чтобыоткройте соединение с ним), на всякий случай, если кто-то поможет, мой код выглядит следующим образом:

class MyFunctionHandler : RequestHandler<Map<String, Any>, ApiGatewayResponse> {

//var dbClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder.defaultClient()
var dbClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder
        .standard().withRegion("sa-east-1").build()

override fun handleRequest(input: Map<String, Any>, context: Context): ApiGatewayResponse {
    LOG.info("received input: $input")

    input["wakeup"]?.let {

        if (it == true) {

            with(EmpresaRepository(dbClient)) {
                LOG.info("### Connection was not stablished at this point")

                someDynamoQueryHere("dummyParameter")

                LOG.info("### The Connection was opened and will keep alived for 1 minute")
            }

            return buildResponseForWakeUpReq(input)
        }
    }

    val param = input["queryStringParameters"]?.toString()
...

Последующие операции, которые откроют соединение DynamoDb, будут происходить в миллисекундах!

0 голосов
/ 27 июня 2019

Все функции aws ClientBuilder.build () занимают некоторое время в лямбде и зависят от памяти, выделенной для функции.Однако, если контейнер уже инициализирован и вы вызываете ClientBuilder.build () во второй раз или при последующем запросе, это происходит в миллисекундах, а не секундах.

0 голосов
/ 23 мая 2018

Согласно этой записи от сотрудника AWS на форумах AWS, строительство объекта AmazonDynamoDB обходится дорого.Перемещение конструкции (назад) в статический инициализатор в сочетании с небольшим выделением дополнительной памяти (= ЦП) в основном решает проблему.

Данные из журналов по-прежнему показывают, что каждый из 2 медленных шагов, указанных выше, занимает примерно половинувремя.Следовательно, по-видимому, как построение, так и первое использование объектов AmazonDynamoDB являются медленными.

Очевидно, что это не поможет с первым запросом, который все еще занимает то же время, что и в вопросе.Однако после того, как лямбда нагреется, последующие запросы будут занимать ~ 15 мс (значительно ниже минимального порога выставления счета в 100 мс).Решение первой проблемы с запросом хорошо понято - например, с помощью CloudWatch Events, чтобы запланировать регулярный вызов лямбды, чтобы она оставалась теплой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...