Serverlessなフレームワークを持つAWSラムダへのNESTJS APIの配備
34883 ワード
あなたはどのように展開し、APIをホストすることができますどのように簡単に疑問がありますか?スケーラブル、安定、ケーキの一部を展開し、ほとんど何もコスト.この記事の目的は、それを証明することです.私たちは、APIゲートウェイの背後にある単一のラムダ関数としてAWSクラウドに配備される単純なAPIを開発します.ラムダがそのように使用されるべきかどうかは、私が喜んでビールを議論する異なった話題です.🙂🍺
我々は、ちょうどNESTJSフレームワークとそのきちんとした開発経験の表面をひっかいます.一旦Serverlessなフレームワークでそれを配線するならば、我々のAPIがどれくらい速く日の光を見ることができるかについて学びます.これを実証するために、私たちは歌のデータベースを管理するAPI -歌APIを作成します、そして、我々はそれが役に立たないと偽ります.
曲のAPIは、データベース内のすべての曲のリストには、単一の曲の詳細を取得し、曲を削除するエンドポイントを公開します.要件を与えられて、歌モデルは特性を持ちます
NestJS - 静的サイドアプリケーションを作成するための強力なフレームワーク
TypeORM - TypeScriptのためのORMライブラリは、データベースアクセスのために巣とうまく統合されます
Serverless Framework - 簡単に使用してフレームワークを開発し、サーバーレスアプリケーションを展開
Serverless Jetpack - 我々のコードをAWSラムダに展開するパッケージを設定する低configプラグイン
Serverless Express - 我々の「プレーンな」NESTJS APIを作る図書館は、Serverlessでうまく遊びます 管理サービスLambda , API Gateway and RDS
私はそれが楽しいと簡単に十分なので、掘りましょうね.
モジュールのスケルトンを生成する便利だったが、もちろん我々のビジネスロジックを記述する必要があります.おそらく、我々はすべての生成されたDTsを必要としないでしょう、我々はコントローラに若干の経路を変えるか、加えるかもしれません、そして、もちろん、我々の実体を実装する必要があります.
typeRM依存関係をインストールしたので、上記の仕様に従って、曲エンティティのオブジェクトリレーショナルマッピングを構成するために使用しましょう.
データベースはかなり数回言及されていますが、どこですか?🤔
まず、ローカルのMySQLデータベースに対してコードをテストしましょう.ローカルサーバーに接続したら、次のinitスクリプトを実行します.
種類
注意1 :既にAWSアカウントを持っていると仮定します.
注2 :手順に従う十分な権限があることを確認してください.IAMユーザの場合、ショートカットは
AWS資格情報ファイルにプロファイルを追加します.
これまでのところ、我々は正常にローカルMySQLデータベースを使用してAPIをテストしてきましたが、今私たちはAWS上で1つが必要です.AWSコンソールで手動で行うことができます.
警告:あなたのアカウントの価格設定と自由層適格性についてお知らせください.すべての新しいAWSの顧客は、特定のサービスのための無料ティアの1年間を取得する必要があります.さもなければ、あなたは公式AWS RDS価格設定ガイドで説明されるように若干のコストを被るかもしれませんhttps://aws.amazon.com/rds/mysql/pricing
データベースURLをRWSに移動したり、次のコマンドを使用してCloudFormationのエクスポートを一覧表示することでAWSコンソールを取得します.
今私たちのデータベースは、クラウドで実行されている、それはローカルの1つの代わりにRDSのデータベースで動作するように我々のアプリを再構成する時間です-ので、URL、パスワード、残りのような関連する詳細を更新することを忘れないでください
ServerlessフレームワークCLIをインストールします
注意
NPMを使用してdev依存関係としてインストールします.
インストール
最後に、APIをクラウドに配備します.これはかなり簡単です.最初にビルドする必要があります.
あなたのAPIを少し再生した後、それはあなたのAWSクラウドで作成されたすべてのリソースをクリーンアップするための時間です.この手順を厳密に実行すると、2つのCloudFormationスタックが配備されます.データベースには1つ、Serverless展開に対しては次のようになります.コンソールを介して手動で削除するか、次のCLIコマンドを実行します.
私は、あなたがこれまでにそれを作ったことを望みます、そして、私はあなたにあまり退屈しませんでした.主な焦点はAWSラムダでのServerlessな展開についてであったが、この記事ではTorrmを使った簡単なNSTEJSプロジェクトを設定し、CloudFormationを通してAWS上のRDS MySQLデータベースインスタンスを作成するような方法をいくつか取り上げた.
この種のAPIがより良いスケールになるのは素晴らしいことですRDS Proxy データベースの先頭にあります.また、AWS認知を使用することによってユーザー認証を加えることは、このセットアップにうまく合う何かです.非常に最近Lambda function URL 機能は、APIゲートウェイの必要性を排除するが、他のトレードオフを持っています.
確かにいくつかのセキュリティ面でこれを議論する価値があるこれは生産準備になるが、それはこの記事の範囲を超えています.
読んでいただきありがとうございます、ご質問やご提案があればコメントを自由に感じる!
この記事から何を期待するのですか。
我々は、ちょうどNESTJSフレームワークとそのきちんとした開発経験の表面をひっかいます.一旦Serverlessなフレームワークでそれを配線するならば、我々のAPIがどれくらい速く日の光を見ることができるかについて学びます.これを実証するために、私たちは歌のデータベースを管理するAPI -歌APIを作成します、そして、我々はそれが役に立たないと偽ります.
要件
曲のAPIは、データベース内のすべての曲のリストには、単一の曲の詳細を取得し、曲を削除するエンドポイントを公開します.要件を与えられて、歌モデルは特性を持ちます
id
, name
, artist
, length
秒単位でgenre
and album
. APIエンドポイントは次のようになります.GET songs
GET songs/:id
POST songs
DELETE songs/:id
テックスタック
NestJS - 静的サイドアプリケーションを作成するための強力なフレームワーク
TypeORM - TypeScriptのためのORMライブラリは、データベースアクセスのために巣とうまく統合されます
Serverless Framework - 簡単に使用してフレームワークを開発し、サーバーレスアプリケーションを展開
Serverless Jetpack - 我々のコードをAWSラムダに展開するパッケージを設定する低configプラグイン
Serverless Express - 我々の「プレーンな」NESTJS APIを作る図書館は、Serverlessでうまく遊びます
巣CLIをインストールし、新しいプロジェクトとモジュールを作る
npm i -g @nestjs/cli
nest new songs-api
この時点でAPIは既に設定されていますnpm run start
オープンlocalhost:3000
Hello World Responseを見るにはこれは可能ですmain.ts
プロジェクトルートで生成されるファイル:import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
今、私たちは創造するつもりですsong
モジュールで、コントローラ、サービス、エンティティ定義を含みます.これらのそれぞれを個別に作成することができますが、ネストCLIは、モジュールを作成するための有用なコマンドを提供し、すべての必要なファイルを1つの移動します.残りのAPIを作成するときに便利です.nest generate resource song
の骨格song
モジュールが生成されます.次に、データベースにアクセスするための依存関係をインストールする必要があります.APIはMySQLデータベースの上で実行されるので、次のライブラリをプロジェクトに追加する必要があります.npm install --save @nestjs/typeorm typeorm mysql2
実装
モジュールのスケルトンを生成する便利だったが、もちろん我々のビジネスロジックを記述する必要があります.おそらく、我々はすべての生成されたDTsを必要としないでしょう、我々はコントローラに若干の経路を変えるか、加えるかもしれません、そして、もちろん、我々の実体を実装する必要があります.
typeRM依存関係をインストールしたので、上記の仕様に従って、曲エンティティのオブジェクトリレーショナルマッピングを構成するために使用しましょう.
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Song {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
artist: string;
@Column()
duration: number;
@Column()
genre: string;
@Column()
album: string;
}
今ではモジュール定義にimportを追加する必要があります.import { Module } from '@nestjs/common';
import { SongService } from './song.service';
import { SongController } from './song.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Song } from './entities/song.entity';
@Module({
imports: [TypeOrmModule.forFeature([Song])],
controllers: [SongController],
providers: [SongService],
})
export class SongModule {
}
さて、サービス層を実装しましょう.SongService
用途Repository
typeRMがデータベースにアクセスするために提供されます.import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Song } from './entities/song.entity';
@Injectable()
export class SongService {
constructor(
@InjectRepository(Song) private songRepository: Repository<Song>,
) {
}
async create(song: Song): Promise<Song> {
return await this.songRepository.save(song);
}
async findAll(): Promise<Song[]> {
return await this.songRepository.find();
}
async findOne(id: number): Promise<Song> {
return await this.songRepository.findOne({ id });
}
async remove(id: number): Promise<void> {
await this.songRepository.delete(id);
}
}
簡単にするために、私はDTOとして実体を再利用するでしょうdto
生成されたフォルダ.それから、コントローラとサービスは次のように書き換えられます.import { Body, Controller, Delete, Get, Param, ParseIntPipe, Post } from '@nestjs/common';
import { SongService } from './song.service';
import { Song } from './entities/song.entity';
@Controller('songs')
export class SongController {
constructor(private readonly songService: SongService) {
}
@Post()
async create(@Body() song: Song): Promise<Song> {
return await this.songService.create(song);
}
@Get()
async findAll(): Promise<Song[]> {
return await this.songService.findAll();
}
@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number): Promise<Song> {
return await this.songService.findOne(id);
}
@Delete(':id')
async remove(@Param('id', ParseIntPipe) id: number): Promise<void> {
await this.songService.remove(id);
}
}
一般的なルールとしては、DTDとエンティティクラスの両方に対して常に良いです.データベース
データベースはかなり数回言及されていますが、どこですか?🤔
まず、ローカルのMySQLデータベースに対してコードをテストしましょう.ローカルサーバーに接続したら、次のinitスクリプトを実行します.
CREATE DATABASE `songsapi`;
USE `songsapi`;
CREATE TABLE `song`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`artist` varchar(200) NOT NULL,
`duration` int(11) DEFAULT NULL,
`genre` varchar(45) DEFAULT NULL,
`album` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
その後、APIは、次の設定を追加することによって、それに接続できることを確認しますapp.module.ts
:import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { SongModule } from './song/song.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'xxx',
database: 'songsapi',
autoLoadEntities: true,
}),
SongModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
上記の値は、ローカルデータベースの設定に対応するハードコードを自由に感じてください.実行する🚀
種類
npm run start
ターミナルで、そして、数秒で、それは起きていて、走らなければなりません.リクエストを送信してテストします.curl -X POST 'localhost:3000/songs' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "In corpore sano",
"artist": "Konstrakta",
"duration": 182,
"album": "In corpore sano",
"genre": "pop"
}'
# Response:
# {"name":"In corpore sano","artist":"Konstrakta","duration":182,"album":"In corpore sano","genre":"pop","id":1}
# Get a single song by id
curl 'localhost:3000/songs/1'
# Response:
# {"name":"In corpore sano","artist":"Konstrakta","duration":182,"album":"In corpore sano","genre":"pop","id":1}
動く!我々はローカルAPIをテストした今、それは雲に展開し、それが世界に利用できるようにする時だ!クラウドへの移行🌥
注意1 :既にAWSアカウントを持っていると仮定します.
注2 :手順に従う十分な権限があることを確認してください.IAMユーザの場合、ショートカットは
arn:aws:iam::aws:policy/AdministratorAccess
管理ポリシーを添付.AWSアカウント資格情報の設定
AWS資格情報ファイルにプロファイルを追加します.
...
[profile-name]
region=your_region
aws_access_key_id=xxx
aws_secret_access_key=yyy
aws_session_token=... (if applicable)
...
その後、環境変数を設定してプロファイルをアクティブにします.export AWS_PROFILE=profile-name
あなたはAWSクラウドと対話する準備ができているはずです.aws s3 ls
フリーティアRDSデータベースのスピンアップ
これまでのところ、我々は正常にローカルMySQLデータベースを使用してAPIをテストしてきましたが、今私たちはAWS上で1つが必要です.AWSコンソールで手動で行うことができます.
警告:あなたのアカウントの価格設定と自由層適格性についてお知らせください.すべての新しいAWSの顧客は、特定のサービスのための無料ティアの1年間を取得する必要があります.さもなければ、あなたは公式AWS RDS価格設定ガイドで説明されるように若干のコストを被るかもしれませんhttps://aws.amazon.com/rds/mysql/pricing
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SongsDatabase:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: 20
DBInstanceClass: db.t3.micro
DBInstanceIdentifier: songs-database
PubliclyAccessible: true
StorageType: gp2
MasterUsername: xxx # change
MasterUserPassword: yyy # change
Engine: mysql
EngineVersion: 8.0.28
上記のファイルをRDSとして保存します.例えばYAMLで、AWS CLIを使います.aws cloudformation deploy --stack-name songs-api-db --template-file rds.yaml
数分でデータベースが準備されます.データベースURLをRWSに移動したり、次のコマンドを使用してCloudFormationのエクスポートを一覧表示することでAWSコンソールを取得します.
aws cloudformation list-exports
. ローカルのインスタンスで行われたデータベースのinitスクリプトを実行します.今私たちのデータベースは、クラウドで実行されている、それはローカルの1つの代わりにRDSのデータベースで動作するように我々のアプリを再構成する時間です-ので、URL、パスワード、残りのような関連する詳細を更新することを忘れないでください
app.module.ts
ファイル.その後は、次のSTEでカバーされる展開する準備が整いました.Serverlessフレームワークのインストールと設定
ServerlessフレームワークCLIをインストールします
npm install -g serverless
プロジェクトの根源に、我々はserverless.yaml
配備を記述するファイル:service: songs-api
frameworkVersion: '3'
plugins:
- serverless-jetpack
provider:
name: aws
runtime: nodejs14.x
region: eu-central-1 # or whatever your region is
functions:
api:
handler: dist/lambda.handler
events:
- http:
method: any
path: /{proxy+}
この設定では、APIゲートウェイは、ラムダ関数と我々のNESTJSアプリは、それを処理するプロキシごとに要求されます.The handler
値は、我々のアプリのエントリポイントを含むファイルであり、分で説明されます.注意
serverless-jetpack
プラグイン-それはServerlessのために非常に効率的に我々のアプリを包装の世話をする.これには他のプラグインがありますが、最近これを発見しました.これまで使ってきた人よりもずっと速いです.続きを読むits official github page .NPMを使用してdev依存関係としてインストールします.
npm i -D serverless-jetpack
ここでは、ラムダ環境で動作するようにAPI - Serverless Expressライブラリを展開する前にもう一つの手順があります.サーバーレスエクスプレス
インストール
serverless-express
Bootstrapsを使用するライブラリは、ラムダで動作するようにアプリケーションを表現しますnpm i @vendia/serverless-express
次に、ソースフォルダでlambda.ts
上記で参照したように、エントリポイントであるラムダハンドラ関数を含むファイルserverless.yaml
.import { configure as serverlessExpress } from '@vendia/serverless-express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
let cachedServer;
export const handler = async (event, context) => {
if (!cachedServer) {
const nestApp = await NestFactory.create(AppModule);
await nestApp.init();
cachedServer = serverlessExpress({ app: nestApp.getHttpAdapter().getInstance() });
}
return cachedServer(event, context);
}
ビルド、配備、テスト🚀
最後に、APIをクラウドに配備します.これはかなり簡単です.最初にビルドする必要があります.
npm run build
... それから、serverless deploy
すぐに、あなたはそれを追加し、リストを削除し、曲を削除することによってそれをテストするために自由に感じ、APIをヒットするために使用できる自動生成されたURLを取得します.あなたはログを見ることができますし、アプリを実行する方法を監視ラムダとCloudWatch AWS管理コンソールのサービスクリーンアップ
あなたのAPIを少し再生した後、それはあなたのAWSクラウドで作成されたすべてのリソースをクリーンアップするための時間です.この手順を厳密に実行すると、2つのCloudFormationスタックが配備されます.データベースには1つ、Serverless展開に対しては次のようになります.コンソールを介して手動で削除するか、次のCLIコマンドを実行します.
serverless remove
aws cloudformation delete-stack --stack-name songs-api-db
結論と最終思考
私は、あなたがこれまでにそれを作ったことを望みます、そして、私はあなたにあまり退屈しませんでした.主な焦点はAWSラムダでのServerlessな展開についてであったが、この記事ではTorrmを使った簡単なNSTEJSプロジェクトを設定し、CloudFormationを通してAWS上のRDS MySQLデータベースインスタンスを作成するような方法をいくつか取り上げた.
この種のAPIがより良いスケールになるのは素晴らしいことですRDS Proxy データベースの先頭にあります.また、AWS認知を使用することによってユーザー認証を加えることは、このセットアップにうまく合う何かです.非常に最近Lambda function URL 機能は、APIゲートウェイの必要性を排除するが、他のトレードオフを持っています.
確かにいくつかのセキュリティ面でこれを議論する価値があるこれは生産準備になるが、それはこの記事の範囲を超えています.
読んでいただきありがとうございます、ご質問やご提案があればコメントを自由に感じる!
Reference
この問題について(Serverlessなフレームワークを持つAWSラムダへのNESTJS APIの配備), 我々は、より多くの情報をここで見つけました https://dev.to/imflamboyant/deploy-a-nestjs-api-to-aws-lambda-with-serverless-framework-4pooテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol