Единицы емкости чтения / записи, предоставленные DynamoDB, неожиданно превышены - PullRequest
0 голосов
/ 01 апреля 2019

Я запускаю программу, которая отправляет данные в DynamodB, используя API-шлюз и лямбда-выражения.

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

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

Может ли кто-нибудь понять из рисунка ниже то, что произошло в 03/13, что вызвало эту пику в диаграммах и вызвало рост этих резервов с 50 до 65?

enter image description here

enter image description here

1 Ответ

0 голосов
/ 01 апреля 2019

Я не могу сказать, что произошло, основываясь только на этих графиках, но некоторые вещи нужно учитывать:

Возможно, вы не знаете о новой опции режима выставления счетов "PAY_PER_REQUEST" для таблиц DynamoDB, которая позволяет вам в большинстве случаев забыть о настройке пропускной способности вручную: https://aws.amazon.com/blogs/aws/amazon-dynamodb-on-demand-no-capacity-planning-and-pay-per-request-pricing/

Кроме того, может не иметь смысла для вашего варианта использования, но для проектов бесплатного уровня я считаю полезным прокси все записи в DynamoDB через очередь SQS (используйте эту очередь в качестве источника событий для Lambda с зарезервированным параллелизмом это совместимо с вашей подготовленной пропускной способностью). Это легко, если ваш проект разумно управляемый событиями, то есть создайте объект / параметры запроса DynamoDB, запишите в SQS, а затем сделайте следующий шаг - лямбда, запускаемая из потока DynamoDB (поэтому вы не ожидаете синхронного ответа) из операции записи в первую лямбду). Как это:

Пример конфигурации без сервера для лямбды, запускаемой SQS:

dynamodb_proxy:
  description: SQS event function to write to DynamoDB table '${self:custom.dynamodb_table_name}'
  handler: handlers/dynamodb_proxy.handler
  memorySize: 128
  reservedConcurrency: 95 # see custom.dynamodb_active_write_capacity_units
  environment:
    DYNAMODB_TABLE_NAME: ${self:custom.dynamodb_table_name}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:PutItem
      Resource:
        - Fn::GetAtt: [ DynamoDbTable, Arn ]
    - Effect: Allow
      Action:
        - sqs:ReceiveMessage
        - sqs:DeleteMessage
        - sqs:GetQueueAttributes
      Resource:
        - Fn::GetAtt: [ DynamoDbProxySqsQueue, Arn ]
  events:
    - sqs:
        batchSize: 1
        arn:
          Fn::GetAtt: [ DynamoDbProxySqsQueue, Arn ]

Пример записи в SQS:

await sqs.sendMessage({
  MessageBody: JSON.stringify({
    method: 'putItem',
    params: {
      TableName: DYNAMODB_TABLE_NAME,
      Item: {
        ...attributes,
        created_at: {
          S: createdAt.toString(),
        },
        created_ts: {
          N: createdAtTs.toString(),
        },
      },
      ...conditionExpression,
    },
  }),
  QueueUrl: SQS_QUEUE_URL_DYNAMODB_PROXY,
}).promise();

Лямбда, запускаемая SQS:

import retry from 'async-retry';
import { getEnv } from '../lib/common';
import { dynamodb } from '../lib/aws-clients';

const {
  DYNAMODB_TABLE_NAME
} = process.env;

export const handler = async (event) => {
  const message = JSON.parse(event.Records[0].body);

  if (message.params.TableName !== env.DYNAMODB_TABLE_NAME) {
    console.log(`DynamoDB proxy event table '${message.params.TableName}' does not match current table name '${env.DYNAMODB_TABLE_NAME}', skipping.`);
  } else if (message.method === 'putItem') {
    let attemptsTaken;
    await retry(async (bail, attempt) => {
      attemptsTaken = attempt;
      try {
        await dynamodb.putItem(message.params).promise();
      } catch (err) {
        if (err.code && err.code === 'ConditionalCheckFailedException') {
          // expected exception
          // if (message.params.ConditionExpression) {
          //   const conditionExpression = message.params.ConditionExpression;
          //   console.log(`ConditionalCheckFailed: ${conditionExpression}. Skipping.`);
          // }
        } else if (err.code && err.code === 'ProvisionedThroughputExceededException') {
          // retry
          throw err;
        } else {
          bail(err);
        }
      }
    }, {
      retries: 5,
      randomize: true,
    });

    if (attemptsTaken > 1) {
      console.log(`DynamoDB proxy event succeeded after ${attemptsTaken} attempts`);
    }
  } else {
    console.log(`Unsupported method ${message.method}, skipping.`);
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...