4
3

More than 3 years have passed since last update.

DynamoDBクライアントでインスタンスが同じならセッション再利用されるのか実験してみた

Last updated at Posted at 2021-04-28

AWS SDK for JavaScriptを使ってDynamoDBを利用する場合、AWS.DynamoDBインスタンスを生成し、これを通してAPIアクセスを行うことになりますが、その際のセッションがどうなっているのか気になって調べてみました。

お急ぎの方に結論

オプションもしくは環境変数を設定すればセッションは再利用されます。
参考

準備

DynamoDB localを起動し、これにアクセスするコードを用意します。
(DynamoDB localがポート18005で動いています)
TCPセッションの状態はlsof -i@localhostで確認します。

実験1

以下のようなコードを用意しました。
DynamoDBインスタンスは1つ作成し、APIを2回実行します。

import { DynamoDB } from 'aws-sdk';
import { execSync } from 'child_process';

process.env.AWS_REGION = 'ap-northeast-1';

function getDynamoDB() {
  return new DynamoDB({
    endpoint: 'http://localhost:18005',
  });
}

function printSession() {
  try {
    const stdout = execSync('lsof -i@localhost | grep node');
    console.log(stdout.toString());
  } catch (e) {
    console.error('null');
  }
}

async function main() {
  console.log('#0');
  printSession();
  const cl = getDynamoDB();
  console.log('#1');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#2');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#3');
  printSession();
}

main();

以下が出力されました。

#0
null
#1
null
#2
node      98657 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56434->localhost:18005 (CLOSE_WAIT)
#3
node      98657 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56435->localhost:18005 (CLOSE_WAIT)

インスタンス作っても接続はされないんですね。
クライアント側のポートが異なるものが・・・ということは、それぞれでセッションが作られていそうです。

実験2

公式がズバリな記事を用意していました。
Reusing Connections with Keep-Alive in Node.js

keepAliveを設定してみます。

import { DynamoDB } from 'aws-sdk';
import { execSync } from 'child_process';
import * as http from 'http';

process.env.AWS_REGION = 'ap-northeast-1';

function getDynamoDB() {
  return new DynamoDB({
    endpoint: 'http://localhost:18005',
    httpOptions: {
      agent: new http.Agent({
        keepAlive: true,
      }),
    },
  });
}

function printSession() {
  try {
    const stdout = execSync('lsof -i@localhost | grep node');
    console.log(stdout.toString());
  } catch (e) {
    console.error('null');
  }
}

async function main() {
  console.log('#0');
  printSession();
  const cl = getDynamoDB();
  console.log('#1');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#2');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#3');
  printSession();
}

main();

実行すると以下が出力されました。

#0
null
#1
null
#2
node      99003 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56503->localhost:18005 (ESTABLISHED)
#3
node      99003 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56503->localhost:18005 (ESTABLISHED)

ちゃんと再利用されていそうです。

実験3

ちなみに、別インスタンスを作ると?と思って念のための追試です。

import { DynamoDB } from 'aws-sdk';
import { execSync } from 'child_process';
import * as http from 'http';

process.env.AWS_REGION = 'ap-northeast-1';

function getDynamoDB() {
  return new DynamoDB({
    endpoint: 'http://localhost:18005',
    httpOptions: {
      agent: new http.Agent({
        keepAlive: true,
      }),
    },
  });
}

function printSession() {
  try {
    const stdout = execSync('lsof -i@localhost | grep node');
    console.log(stdout.toString());
  } catch (e) {
    console.error('null');
  }
}

async function main() {
  console.log('#0');
  printSession();
  const cl = getDynamoDB();
  console.log('#1');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#2');
  printSession();
  await cl.describeTable({ TableName: 'test-table' }).promise();
  console.log('#3');
  printSession();
  const cl2 = getDynamoDB();
  console.log('#4');
  printSession();
  await cl2.describeTable({ TableName: 'test-table' }).promise();
  console.log('#5');
  printSession();
}

main();

以下が出力されました。

#0
null
#1
null
#2
node      99143 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56510->localhost:18005 (ESTABLISHED)
#3
node      99143 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56510->localhost:18005 (ESTABLISHED)
#4
node      99143 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56510->localhost:18005 (ESTABLISHED)
#5
node      99143 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56510->localhost:18005 (ESTABLISHED)
node      99143 user   35u  IPv4 0x108da27b1d53185d      0t0  TCP localhost:56511->localhost:18005 (ESTABLISHED)

インスタンスまたいで共有はされませんね。

結果

短い時間に複数回の操作を呼び出すユースケースがある場合は、keepAlive設定するか、公式に記載のAWS_NODEJS_CONNECTION_REUSE_ENABLEDを利用するのがよさそうです。

AWS_NODEJS_CONNECTION_REUSE_ENABLEDを設定すると別インスタンスでもセッションが共有されます。

keepAliveを使う場合、この実験ではローカル接続でhttpでしたが、AWS環境で有効にするにはhttps.Agentにする必要があります。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3