DynamoDB PutItem, использующий всю память кучи - NodeJS - PullRequest
0 голосов
/ 11 февраля 2020

У меня есть CSV с более чем миллионом строк, я хочу импортировать все строки в DynamoDB. Я могу l oop через csv просто отлично, однако, когда я пытаюсь вызвать DynamoDB PutItem в этих строках, у меня заканчивается куча памяти после примерно 18k вызовов.

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

let insertIntoDynamoDB = async () => {
  const file = './file.csv';
  let index = 0;

  const readLine = createInterface({
    input: createReadStream(file),
    crlfDelay: Infinity
  });

  readLine.on('line', async (line) => {
    let record = parse(`${line}`, {
      delimiter: ',',
      skip_empty_lines: true,
      skip_lines_with_empty_values: false
    });

    await dynamodb.putItem({
      Item: {
        "Id": {
          S: record[0][2]
        },
        "newId": {
          S: record[0][0]
        }
      },
      TableName: "My-Table-Name"
    }).promise();

    index++;
    if (index % 1000 === 0) {
      console.log(index);
    }
  });
  // halts process until all lines have been processed
  await once(readLine, 'close');

  console.log('FINAL: ' + index);
}

Если я закомментирую вызов Dynamodb, я смогу просто просмотреть файл и прочитать каждую строку. Откуда происходит это использование памяти? Моя пропускная способность записи в DynamoDB составляет 500, настройка на это не влияет.

1 Ответ

0 голосов
/ 12 февраля 2020

Для тех, кто неохотно просматривает inte rnet и пытается выяснить, почему DynamoDB использует всю кучную память, здесь найден отчет об ошибке github: https://github.com/aws/aws-sdk-js/issues/1777#issuecomment -339398912

По сути, aws sdk имеет только 50 сокетов для выполнения http-запросов, если все сокеты используются, то события будут поставлены в очередь, пока сокет не станет доступным. При обработке миллионов запросов эти сокеты немедленно расходуются, а затем очередь накапливается до тех пор, пока не взорвется куча.

Итак, как вы справляетесь с этим?

  1. Увеличение размера кучи
  2. Увеличение количества сокетов
  3. Контроль количества «событий» в очереди

Параметры 1 и 2 легкий путь, но не масштабировать. Они могут работать для вашего сценария, если вы делаете что-то одно, но если вы пытаетесь создать надежное решение, то вам не нужно набирать go с номером 3.

Делать число 3, я определяю максимальный размер кучи и делю его на то, насколько большим, я думаю, будет «событие» в памяти. Например: я предполагаю, что событие updateItem для DynamoDB будет 100 000 байтов. Мой размер кучи был 4 ГБ, поэтому 4 000 000 000 B / 100 000 B = 40 000 событий. Однако я беру только 50% от этого количества событий, чтобы освободить место в куче для других процессов, которые может выполнять приложение узла. Этот процент может быть уменьшен / увеличен в зависимости от ваших предпочтений. Как только у меня есть количество событий, я затем читаю строку из csv и использую событие, когда событие завершено, я выпускаю событие обратно в пул. Если доступных событий нет, то я приостанавливаю поток ввода в CSV, пока событие не станет доступным.

Теперь я могу загружать миллионы записей в Dynamodb, не беспокоясь о том, чтобы взорвать кучу.

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