NodeJSアプリをサーバーレスにする方法

これがこのトピックに関する別の投稿であるため、Serverlessが私と同じように愛されることを願っています。

さて、簡単なサーバーレスREST APIについて話している場合、AWSでの設定は非常に明白です:Lambda + API Gateway。

しかし、バックエンドが持つ可能性のある他の(マイクロ)サービスについてはどうでしょうか?ご存知のように、すべてのアプリケーションコードを単一のモノリシックAWS Lambda関数に配置することは最善のアイデアではありません。

チャレンジ

アプリケーションモジュールをサーバーレスマイクロサービスとして簡単にデプロイし、相互に通信する必要もあります。できれば、サービス間の通信は、ある種のACLによって規制されるべきです。

試行1. API Gateway

これは、問題を解決しようとしていたときに最初に考えたものです。APIGatewayを介してすべてのマイクロサービスを公開するだけです。問題は…作成されたAPIは公開されています。

なぜこれが問題なのですか?たとえば、何らかの認証を使用してアクセスが制限されている場合でも、請求サービスを全世界に公開することは望ましくありません。

APIをプライベートにすることもできますが、セキュリティポリシーはかなり制限されています。

API Gatewayリソースポリシーを使用して、次の方法でAPIを安全に呼び出すことができます。
*指定されたAWSアカウントのユーザー
*指定されたソースIPアドレス範囲またはCIDRブロック
*指定された仮想プライベートクラウド(VPC)またはVPCエンドポイント(アカウント内)

このため、このようなサービス間の通信を制御するのは非常に面倒です。ここでそれを行う唯一の方法は、サービスを別々のVPCに入れることです。

試行2.ラムダ

すべてのマイクロサービスを個別のAWS Lambdaに入れてみませんか?これで問題は解決しますか?

はい、実際にはサーバーレスのマイクロサービスになり、IAMポリシーを使用してサービス間のアクセスを調整できますが、それは「簡単」ではありません。

私はこれがごくごく普通のことであり、展開ユニットとして小さな機能を持っていることを知っています。また、サービスに複数のエンドポイント/メソッド/機能がある場合、複数のLambdaとしてデプロイしても問題ないと見なされます。

私はそれの利点を理解していますが、メンテナンスと開発の容易さを犠牲にします。また、Lambda関数のセットとしてサービスをデプロイするというアイデアは本当に好きではありません。課金を処理するいくつかの個別の機能を想像してください。それはもはや限定されたコンテキストではありません。このような粒度が役立つ場合もありますが、まれなケースです。

試み3.ファットラムダ

実際に一連のエンドポイントを単一のLambdaとしてデプロイできますか(もちろん、API Gatewayを使用せずに)。

これを行うことができれば、前のオプションのすべての利点が得られますが、展開ユニットの粒度を選択することもできます。

私が望む方法は次のとおりです:デプロイ可能な各サービスは、メソッドを備えた単純な古いJSオブジェクトである必要があります。これは、オブジェクトとAWS Lambdaの間に数行のグルーコードを追加することで実現するのは非常に簡単です。

これが私の実装です:aws-rpc。このnodejsモジュールは、オブジェクトを渡すだけのlambdaHandler関数を公開し、Lambdaにアクセスできるすべてのユーザーに自動的に公開されます。

import {lambdaHandler} from 'aws-rpc';
import 'TestServiceImpl} from' ./TestServiceImpl ';
//これはデプロイメントユニットです
//これは、Lambdaのハンドラー関数として指定するものです
export const handler = lambdaHandler(new TestServiceImpl());

これで、「ハンドラ」をAWS Lambdaとしてデプロイできます。メソッドを呼び出す方法は次のとおりです。

'./TestService'から{TestService}をインポートします。
const client = await createClient ( "LambdaName"、 "test");
console.log(await client.test());

クライアントスタブオブジェクトのメソッドを生成できるようにするには、例で行ったように、すべてのメソッド名をcreateClientに渡す必要があることに注意してください。

JSにはTypeScriptインターフェイスに関するランタイム情報がないため、これが必要です。抽象クラスを使用して実装できますが、¯\ _(ツ)_ /¯は好きではありません。

ボーナス!すべてローカルで実行できます!

あなたの地域の開発環境を可能な限り快適にすることが非常に重要だと思います。これが、AWSに何もデプロイせずにサービスとクライアントをローカルで実行する機能も追加した理由です(関数runServiceおよびcreateClientを参照)。例については、GitHubのリポジトリを参照してください。

概要

これは、クラウドプロバイダーが提供するサービスに迷子になりやすく、インフラストラクチャを過剰に設計しやすくなります。

私は常に考えられる最もシンプルで明示的なソリューションを選択します。また、他のプラットフォームから多くのテクニックやプラクティスを再利用できることを常に覚えておいてください(太いNodeJS Lambdaのアイデアは、Javaの世界からのいわゆる太ったjarに触発されています)。

このトピックが気に入ったら、これらもチェックしてください:

  • 最高のサーバーレスアーキテクチャを作成する方法を学ぶ必要があります
  • 無料のサーバーレスCI / CDパイプラインを作成する方法:3つの簡単な例
  • リージョン間でDynamoDBを簡単に複製する方法
  • 多地域アプリケーション(およびPay Zero)の作成方法
  • Java Web Appをサーバーレスにする

コメント、いいね、シェアは大歓迎です。乾杯!