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
にする必要があります。