Share
Embed
Organize your chaotic DynamoDB (with Node.js) / Organize your chaotic DynamoDB with Nodejs
osamu.arita
May 11, 2021
Transcript
35 slides
-
Organize your chaotic DynamoDB (with Node.js) osamu.arita - LINE Fukuoka
GWの自由研究発表会 - 11st/May/2021 -
ABOUT ME • LINE Fukuokaのエンジニア ◦ 以前はiOSエンジニアをしていました ◦ 今は「LINE SMART
CITY GovTech プログラム」の開発サポート全般 • 社会人歴15年 / 社歴1年目 ◦ AWS / Firebase / Ruby on Rails / PHP(Laravel、etc..) ◦ iOS(swift)/ Android(Kotlin / Java)/ Flutter(Dart) • GWは、息子(現5歳)と遊ぶのが中心でした • slack - #z_osamu osamu_arita osamu.arita -
DynamoDBとは • フルマネージド型NoSQLデータベース ◦ プライマリーキー以外はスキーマレス ◦ key-value (wide-column store) およびドキュメントデータモデルをサポート
• 高可用性:3つのAZ(Availability Zone)でレプリケーションを持っている -
RDBMSとNoSQLの比較 RDBMS(RDS) NoSQL(DynamoDB) スキーマ (テーブル定義) スキーマあり プライマリーキー以外はスキーマレス
拡張性 - 高 トランザクション ACID特性 ・原子性 (Atomicity) ・一貫性 (Consistency) ・独立性 (Isolation) ・永続性 (Durability) BASE特性 ・基本的に利用可能 (Basically Available) ・厳密ではない状態遷移 (Soft state) ・結果整合性 (Eventual consistency) 【備考】 ・ConsistentRead(強い整合性のある読み込み)パラメータ あり ・DynamoDB Transactions API:リージョン内でACIDを保 証 操作 SQL ・Classic API ・PartiQL(パーティクル) - SQL互換の クエリ言語 -
DynamoDBのテーブル要素 Partition Key Sort Key Attribute Item Attribute Attribute Attribute
Schema定義 他に Secondary Index もあります LSI - Sort Key以外で絞り込み。テーブル作成時に定義 GSI - Partition Keyを別途設定。後で追加可能。但しコスト大 -
DynamoDBのテーブル要素 Partition Key Sort Key Attribute Item Attribute Attribute Attribute
Schema定義 プログラムなどで動的に追加 -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 ファイルA:table A に「updateAt」追加 ファイルB:table A に「memo」追加 -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 エンジニアCさん参加 -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 エンジニアCさん tableの構成がソースコード上でバラついて 全然わからない! -
DynamoDB操作 - Node.JS • AWS SDK for JavaScriptで提供されているライブラリ ◦
v2 ◦ v3 ◦ 参考 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/welcome.html const {DynamoDB} = require("@aws-sdk/client-dynamodb" ); const { DynamoDBClient, ListTablesCommand }= require('@aws-sdk/client-dynamodb' ); // Commandベースでテーブル一覧取得やテーブル操作など const dbclient = new DynamoDBClient({ region: 'us-west-2' }); var AWS = require('aws-sdk'); AWS.config.update( {region: 'REGION'}); // テーブル一覧取得など var ddb = new AWS.DynamoDB({apiVersion: "2006-03-01" }); // テーブル操作 var docClient = new AWS.DynamoDB. DocumentClient({apiVersion: '2012-08-10' }); -
DynamoDB操作 - Node.JS • AWS SDK for JavaScriptで提供されているライブラリ ◦
v2 ◦ v3 ◦ 参考 ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html ▪ https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/welcome.html const {DynamoDB} = require("@aws-sdk/client-dynamodb" ); const { DynamoDBClient, ListTablesCommand }= require('@aws-sdk/client-dynamodb' ); // Commandベースでテーブル一覧取得やテーブル操作など const dbclient = new DynamoDBClient({ region: 'us-west-2' }); var AWS = require('aws-sdk'); AWS.config.update( {region: 'REGION'}); // テーブル一覧取得など var ddb = new AWS.DynamoDB({apiVersion: "2006-03-01" }); // テーブル操作 var docClient = new AWS.DynamoDB. DocumentClient({apiVersion: '2012-08-10' }); v3のメリット ・SDKがTypeScriptで記述されている ・サービスごとに個別のパッケージが利用可能 ・新しいmiddlewareStack など -
DynamoDB Table定義集約 - Node.JS • Amazon DynamoDB DataMapper For JavaScript
◦ awslabsが提供しているライブラリ ◦ modelを作成することでTable定義を集約できる ◦ 参考 ▪ https://github.com/awslabs/dynamodb-data-mapper-js ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/ @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } -
DynamoDB Table定義集約 - Node.JS • Amazon DynamoDB DataMapper For JavaScript
◦ awslabsが提供しているライブラリ ◦ modelを作成することでTable定義を集約できる ◦ 参考 ▪ https://github.com/awslabs/dynamodb-data-mapper-js ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/ @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } コードとしてはv2に対応 -
DynamoDB Table定義集約 - Node.JS • Amazon DynamoDB DataMapper For JavaScript
◦ awslabsが提供しているライブラリ ◦ modelを作成することでTable定義を集約できる ◦ 参考 ▪ https://github.com/awslabs/dynamodb-data-mapper-js ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/ @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } dynamodb-data-mapper-annotations を利用すると 左記のようにきれいに書けるけれど、 JavaScriptで記載する場合は以下の通り class MyDomainObject { } Object.defineProperties(MyDomainObject.prototype, { [DynamoDbTable]: { value: 'table_name' }, [DynamoDbSchema]: { value: { id: { type: 'String', keyType: 'HASH' }, foo: { type: 'String', keyType: 'RANGE' }, : }, }, }); -
DynamoDB Table定義集約 - Node.JS • Amazon DynamoDB DataMapper For JavaScript
◦ awslabsが提供しているライブラリ ◦ modelを作成することでTable定義を集約できる ◦ 参考 ▪ https://github.com/awslabs/dynamodb-data-mapper-js ▪ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/ @table('table_name') class MyDomainObject { @hashKey() id: string; @rangeKey({defaultProvider: () => new Date()}) createdAt: Date; @attribute() completed?: boolean; } dynamodb-data-mapper-annotationsを利用する場合 tsconfig.jsonで experimentalDecorators と emitDecoratorMetadata オプションを true にする必要あり tsconfig.json { "compilerOptions": { "experimentalDecorators ": true, "emitDecoratorMetadata ": true, } -
DocumentClient(v2)とDataMapperの比較 (1) DocumentClient(v2) DataMapper scan scan(params, callback) ⇒
AWS.Request scan<T extends StringToAnyObjectMap>( valueConstructor: ZeroArgumentsConstructor<T>, options?: ScanOptions|ParallelScanWorkerOptions ): ScanIterator<T>; get get(params, callback) ⇒ AWS.Request get<T extends StringToAnyObjectMap = StringToAnyObjectMap>( item: T, options?: GetOptions ): Promise<T>; put put(params, callback) ⇒ AWS.Request put<T extends StringToAnyObjectMap = StringToAnyObjectMap>( item: T, options?: PutOptions ): Promise<T>; 一通りのメソッドは用意されている。scanは戻り値の型がPromiseではないので注意 -
DocumentClient(v2)とDataMapperの比較 (2) DocumentClient(v2) DataMapper update update(params, callback) ⇒
AWS.Request update<T extends StringToAnyObjectMap = StringToAnyObjectMap>( item: T, options?: UpdateOptions ): Promise<T>; delete delete(params, callback) ⇒ AWS.Request delete<T extends StringToAnyObjectMap = StringToAnyObjectMap>( item: T, options?: DeleteOptions ): Promise<T|undefined>; • 参考 ◦ https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html ◦ https://awslabs.github.io/dynamodb-data-mapper-js/packages/dynamodb-data-mapper/ ◦ https://github.com/awslabs/dynamodb-data-mapper-js/blob/master/packages/dynamodb-data-mapper/src/DataMapper.ts 一通りのメソッドは用意されている -
試してみた構成 エンジニアAさん ・言語:TypeScript(※1) ・DynamoDB:create-table / put-item ・AWS Lambda:create-function
/ delete-function / invoke (※1)dynamodb-data-mapperのサンプルがTypeScriptベース localstack DynamoDB AWS Lambda Node.js テーブル: SurveyResults • 参考 ◦ https://github.com/localstack/localstack ◦ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/workbench.settingup.html ・AWS提供のNoSQL Workbenchで実際のデータ確認 -
試してみた構成 エンジニアAさん ・言語:TypeScript(※1) ・DynamoDB:create-table / put-item ・AWS Lambda:create-function
/ delete-function / invoke (※1)dynamodb-data-mapperのサンプルがTypeScriptベース localstack DynamoDB AWS Lambda Node.js テーブル: SurveyResults • 参考 ◦ https://github.com/localstack/localstack ◦ https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/workbench.settingup.html ・AWS提供のNoSQL Workbenchで実際のデータ確認 ・サービス共通で http://localhost:4566/ にてアクセス可能 ・localstack内でアクセスする場合、 http://${process.env.LOCALSTACK_HOSTNAME}:4566 とLOCALSTACK_HOSTNAMEを利用することでアクセス可能 -
今回作成したリポジトリ https://github.com/noeloasis/localstack-dynamodb 必要に応じて「-g」を「-D」にしてください 事前準備。記載されているコマンドを実行します localstackに接続するためのAWS profileを作成します Access Key,
Secret Access Keyの値は何でも良いですが コード内で指定しているため、このまま入力します -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 エンジニアCさん tableの構成がソースコード上でバラついて 全然わからない! -
とあるプロジェクトの構成 エンジニアAさん リポジトリ エンジニアBさん GitHub commit & push commit &
push deploy (AWS CloudFormation, AWS SAM) pull pull AWS(Serverless構成) DynamoDB AWS Lambda API Gawatey Node.js table A table B ※フロントエンドなど細かい部分は省略 エンジニアCさん tableの構成がソースコード上で わかる(わかりそう)! -
まとめ • カオスなDynamoDB ◦ 複数のエンジニアが開発を行い、table情報がソースコード上でばらついている状態 • DataMapperを利用する事で、モデルとして整理できそう ◦ ただし・・
▪ scanの戻り値の型がScanIteratorでPromiseと異なるので注意 ▪ AWS SDK for JavaScript (v3) を利用したい場合は、別の方法を検討 • DynamoDBを試したい場合、localstack+NoSQL Workbenchは便利!