【re:Invent 2022】分離されたマイクロサービスのワークショップに参加してきました
AWS re:Invent 2022で行われた、「Decoupled microservices」のワークショップレポートです
この記事は、要点・見どころ・ポイントについてまとめます
所要時間10分程度
ワークショップ概要
Title
Decoupled microservices
分離されたマイクロサービス
Overview
Companies may deal with integration challenges in many areas and on many layers, and all integration approaches come with their individual trade-offs. However, loosely coupled integration can not only help with designing independent systems that can be developed and operated individually but can also increase availability and reliability of the overall systems landscape. In this workshop, implement fundamental integration patterns in a serverless microservices scenario on AWS. The focus is on standard integration patterns for loose coupling and asynchronous communication and how simply they can be implemented with cloud-native services on AWS. You must bring your laptop to participate.
企業は多くの分野、多くのレイヤーで統合の課題に取り組む可能性があり、すべての統合アプローチには個々のトレードオフが伴います。しかし、疎結合の統合は、個別に開発・運用できる独立したシステムの設計に役立つだけでなく、システム全体のランドスケープにおける可用性と信頼性を向上させることが可能です。このワークショップでは、AWS上のサーバーレスマイクロサービスシナリオで基本的な統合パターンを実装します。疎結合と非同期通信のための標準的な統合パターンに焦点を当て、それらがいかにシンプルにAWS上のクラウドネイティブサービスで実装できるかを説明します。参加にはノートPCの持参が必要です。
Services
Amazon EventBridge, Amazon Simple Notification Service (SNS), Amazon Simple Queue Service (SQS)
Session type
Workshop
Speakers
- Mithun Mallick, Principal Specialist SA, Integration Services, AWS
- Dirk Fröhner, Principal Solutions Architect, Amazon Web Services
Report
2時間内での作業となりました
会場の雰囲気
ワークショップのためPC持参で、もくもく会のような雰囲気でした
参加者数は50名程度で満席になりました
そもそもマイクロサービスとは?
簡単に説明すると小さな独立した複数のサービスで、ソフトウェアを構成するアプローチ手法です
開発期間を短縮できたり、スケーリング、耐障害性、他サービスへの影響を与えないなど色々メリットあります
マイクロサービスをもっと知りたい方はこちら↓
ワークショップスタート
今回ネタとなるお題は..
今からユニコーン位置情報のアプリをマイクロサービスで実現させっぞ!
AWSではよくお題でユニコーンのキャラクターが出題・登場します
要件
各ユニコーン(エンドユーザーで捉えてもらえばよい)には、位置情報やバイタルサインを報告するセンサーがついてます
あなたはWild Rydesアプリを提供してる架空の会社を運営していて、いろんなユニコーン提供者が、Wild Rydesと提携するためにプラットフォームが用意されてます
Wild Rydesアプリを利用する顧客は、モバイルアプリからの乗車リクエストを送信できます
という 仮想の設定内容 でワークショップを進めていきます
ここはそういうお題なんだってことで把握だけしておきましょう
そしてここから、非同期メッセージングを使用して、マイクロサービス化されたサーバーレスアプリケーションを構築します
自分の冒険を選ぼう
出題された4つのラボから、どれかを選んで実践することになりました
今回は、 「ラボ2: Topic-queue chaining & load balancing(トピックキューチェーンと負荷分散)」 を選択しました
そして、ユニコーンの乗車完了通知は↓の構成になります
上記のようなマイクロサービスアーキテクチャで、「トピックキューチェーンと負荷分散」のラボを実践していきます
大まかな流れとしては
- Wild Rydesアプリのユニコーンからリクエスト
- API Gateway + Compute(乗り物プロセッサー)の乗車サービスを起動
- 以降、各コンポーネントサービスへ水平で起動させる仕組みを構成
- 顧客通知サービスへ
- 顧客会計サービスへ
- 顧客忠実サービスへ
- データレイク統合サービスへ
- レスポンス
ここから作業が始まります
ワークショップ前提条件
AWSアカウント用意
予めre:Invent運営側で、今回のワークショップのためにAWSアカウントが用意されたのでそちらを利用しました
AWSアカウントがない場合は作成しましょう(無料利用枠あり)
IDE Cloud9の用意
こちらも同様にre:Invent運営側で、CloudFormationで作成されたCloud9のスタックが用意されていましたので、Cloud9にログインします
クラウドの統合開発環境(IDE)Cloud9で開発環境を用意するための設定ファイルを準備しました
Cloud9に既に用意されていたソースコードは↓から確認できます
【実践!!】Topic-queue chaining & load balancing Architecture
リソースの作成と設定
AWSマネジメントコンソールから作成するケースも記載されてましたが、手っ取り早くAWS SAM CLIを利用してデプロイするやり方にしました
AWS SAMは、YAML構文でサーバーレスアプリケーションを構築することができるフレームワークです
Cloud9起動後に事前にSAM CLIも利用できるようになっていたのでそのまま作業に取り掛かります
初期設定
統合を含むユニコーン管理サービスの初期設定を構築します
ここで用意するのはAPIGateway, サービスごとのLambda、DynamoDBです
sam cliを利用してビルドを行い、アプリケーションをデプロイします
$ sam build
$ export AWS_REGION=$(aws --profile default configure get region)
$ sam deploy \
--stack-name wild-rydes-async-msg-2 \
--capabilities CAPABILITY_IAM \
--region $AWS_REGION \
--guided
sam deploy時に確認項目が入りますがSubmitRideCompletionFunctionの承認定義の質問事項をyes
で回答して、それ以外はデフォルトでEnterを押して進みます
CloudFormationでスタックが作成され、CREATE_COMPLETE
後にリソースが作られたかどうか確認します
Amazon SNSトピックを作成
ここから乗車サービスのLambdaからSNSトピックをPublishするため、Amazon SNSトピックを作成します
Cloud9上で用意されているラボごとのディレクトリに用意されているtemplate.yaml
にSNSリソースを追加していきます
RideCompletionTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: RideCompletionTopic
追加したリソースをビルド後、デプロイします
$ sam build
$ sam deploy
これでSNSが作成されます
顧客通知サービスのサブスクリプションを作成
ここでは顧客通知サービスで利用するAmazon SNSのサブスクリプション経由で起動させるAmazon SQSのキューを作成していきます
template.yaml
に追加するリソース、ポリシーを追加します
# SQSを標準キューとして定義
CustomerNotificationServiceQueue:
Type: AWS::SQS::Queue
# SNSにSQSに対してPublishするポリシーを定義
CustomerNotificationServiceQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref CustomerNotificationServiceQueue
PolicyDocument:
Statement:
Effect: Allow
Principal: '*'
Action: sqs:SendMessage
Resource: '*'
Condition:
ArnEquals:
aws:SourceArn: !Ref RideCompletionTopic
# SNSのサブスクリプションフィルターにSQSのArnを定義
CustomerNotificationServiceQueueToRidesTopicSubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: !GetAtt CustomerNotificationServiceQueue.Arn
Protocol: sqs
RawMessageDelivery: true
TopicArn: !Ref RideCompletionTopic
# 顧客通知サービスのLanbdaに対してSQSからの起動とアクセス権限のポリシーも定義
CustomerNotificationService:
Type: AWS::Serverless::Function
Properties:
CodeUri: generic-backend-microservice/
Handler: app.lambda_handler
ReservedConcurrentExecutions: 5
Environment:
Variables:
SERVICE_NAME: CustomerNotificationService
Policies:
- SQSPollerPolicy:
QueueName: !Ref CustomerNotificationServiceQueue
Events:
CustomerNotificationServiceJobQueue:
Type: SQS
Properties:
Queue: !GetAtt CustomerNotificationServiceQueue.Arn
BatchSize: 1
追加したリソースをビルド後、デプロイします
$ sam build
$ sam deploy
新しいAmazon SQSキューとAmazon SNSサブスクリプションをデプロイされたかを確認します
顧客会計サービスのサブスクリプションを作成
次に顧客会計サービスのAWSリソースも同様に作成していきます
# SQSを標準キューとして定義
CustomerAccountingServiceQueue:
Type: AWS::SQS::Queue
# SNSにSQSに対してPublishするポリシーを定義
CustomerAccountingServiceQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref CustomerAccountingServiceQueue
PolicyDocument:
Statement:
Effect: Allow
Principal: '*'
Action: sqs:SendMessage
Resource: '*'
Condition:
ArnEquals:
aws:SourceArn: !Ref RideCompletionTopic
# SNSのサブスクリプションフィルターにSQSのArnを定義
CustomerAccountingServiceQueueToRidesTopicSubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: !GetAtt CustomerAccountingServiceQueue.Arn
Protocol: sqs
RawMessageDelivery: true
TopicArn: !Ref RideCompletionTopic
# 顧客会計サービスのLanbdaに対してSQSからの起動とアクセス権限のポリシーも定義
CustomerAccountingService:
Type: AWS::Serverless::Function
Properties:
CodeUri: generic-backend-microservice/
Handler: app.lambda_handler
ReservedConcurrentExecutions: 5
Environment:
Variables:
SERVICE_NAME: CustomerAccountingService
Policies:
- SQSPollerPolicy:
QueueName: !Ref CustomerAccountingServiceQueue
Events:
CustomerAccountingServiceJobQueue:
Type: SQS
Properties:
Queue: !GetAtt CustomerAccountingServiceQueue.Arn
BatchSize: 1
追加したリソースをビルド後、デプロイします
$ sam build
$ sam deploy
新しいAmazon SQSキューとAmazon SNSサブスクリプションをデプロイされたかを確認します
並外れな乗り物サービスのサブスクリプションを作成
こちらも上記2点のサービスと同じ流れでAWSリソースを作成していきます
# SQSを標準キューとして定義
ExtraordinaryRidesServiceQueue:
Type: AWS::SQS::Queue
# SNSにSQSに対してPublishするポリシーを定義
ExtraordinaryRidesServiceQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref ExtraordinaryRidesServiceQueue
PolicyDocument:
Statement:
Effect: Allow
Principal: '*'
Action: sqs:SendMessage
Resource: '*'
Condition:
ArnEquals:
aws:SourceArn: !Ref RideCompletionTopic
# SNSのサブスクリプションフィルターにSQSのArnを定義
ExtraordinaryRidesServiceQueueToRidesTopicSubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: !GetAtt ExtraordinaryRidesServiceQueue.Arn
Protocol: sqs
RawMessageDelivery: true
TopicArn: !Ref RideCompletionTopic
FilterPolicy: { "fare": [{"numeric": [">=", 50]}], "distance": [{"numeric": [">=", 20]}] }
# 並外れな乗り物サービスのLanbdaに対してSQSからの起動とアクセス権限のポリシーも定義
ExtraordinaryRidesService:
Type: AWS::Serverless::Function
Properties:
CodeUri: generic-backend-microservice/
Handler: app.lambda_handler
ReservedConcurrentExecutions: 5
Environment:
Variables:
SERVICE_NAME: ExtraordinaryRidesService
Policies:
- SQSPollerPolicy:
QueueName: !Ref ExtraordinaryRidesServiceQueue
Events:
ExtraordinaryRidesServiceJobQueue:
Type: SQS
Properties:
Queue: !GetAtt ExtraordinaryRidesServiceQueue.Arn
BatchSize: 1
追加したリソースをビルド後、デプロイします
$ sam build
$ sam deploy
新しいAmazon SQSキューとAmazon SNSサブスクリプションをデプロイされたかを確認します
ユニコーン管理サービスを更新
ここまで作業が完了していると現状構成は下記のようになっています
ここからLambda関数にAmazon SNSの公開メッセージ許可を付与するポリシーを追加します
Resources:
SubmitRideCompletionFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: unicorn-management-service/
Handler: app.lambda_handler
Environment:
Variables:
TABLE_NAME: !Ref RidesTable
# SNSのトピックArnを追加
TOPIC_ARN: !Ref RideCompletionTopic
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref RidesTable
# SNSをPublishするアクセス許可設定されてるポリシーを追加
- SNSPublishMessagePolicy:
TopicName: !GetAtt RideCompletionTopic.TopicName
Events:
WildRydes:
Type: Api
Properties:
Path: /submit-ride-completion
Method: post
続いて、Lambdaハンドラーapp.py
にSNSトピックをPublishするように、処理を変更します
config = Config(connect_timeout=5, read_timeout=5, retries={'max_attempts': 1})
dynamodb = boto3.client('dynamodb', config=config)
# Lambda内からSNS操作を行うため、追加
sns = boto3.client('sns', config=config)
response = dynamodb.put_item(
TableName=TABLE_NAME,
Item={
'id': {'S': id},
'from': {'S': request['from']},
'to': {'S': request['to']},
'duration': {'N': str(request['duration'])},
'distance': {'N': str(request['distance'])},
'customer': {'S': request['customer']},
'fare': {'N': str(request['fare'])}
}
)
# Lambda内からSNS操作を行うため、追加
response = sns.publish(
TopicArn=TOPIC_ARN,
Message=json.dumps(request),
MessageAttributes = {
'fare': {
'DataType': 'Number',
'StringValue': str(request['fare'])
},
'distance': {
'DataType': 'Number',
'StringValue': str(request['distance'])
}
}
)
追加/変更したリソースをビルド後、デプロイします
$ sam build
$ sam deploy
これでアプリケーションの構築は一通り終わりました
つぎに確認に進みます
テストする
Amazon SNSトピックがすべてのメッセージをすべてのサブスクライバーにPublishしていることを検証していきます
サブスクライバーもメッセージの処理に失敗する可能性があるので、Amazon SNSがメッセージを再配信していることも検証します
curlコマンドを使って擬似的にユニコーンからアクセスさせます
並外れな乗り物サービスのフィルターをテストするときは、リクエストペイロードを変更して5回以上APIを実行してください
curl -XPOST -i -H "Content-Type\:application/json" -d '{ "from": "Berlin", "to": "Frankfurt", "duration": 420, "distance": 600, "customer": "cmr", "fare": 256.50 }' $ENDPOINT
結果として処理に失敗された場合に、Amazon SNSからのメッセージの再配信をしていることで負荷分散
テストして成功するか確認しましょう! 上手くいけば起動されます
今回のワークショップはここまでです
説明に含めてませんが、ラボ1,3,4もやってみたい方はこちらから実践可能です
あとは作成したリソースを使わない場合、料金発生するので消しましょう
まとめ
AWS SAMを利用した構築だとマネジメントコンソールからAWSリソースを作るより、手っ取り早く構築ができるので便利だなと再確認できたのは事実
ただし、理解ができてないレベルであればAWS SAMを使うより、まずはマネジメントコンソールからAWSリソースを作成して知識を身に着けていくことがいいでしょう
時間があれば、全てのラボをやってみると分離されたマイクロサービスの理解がより深まるのではと考えています。
以上
Discussion