AWS Developer Associate 合格体験記/学習方法 [AWS認定4冠]

  • AWS Developer Associate 合格までの学習方法についての記録
  • 先にSAA, SOAを取得していたので、これでアソシエイト3種をコンプできました
  • SAA/SOAとDVAは試験の毛色が大分違う為相応の準備が必要でした
  • AWS認定のオンライン試験も初めてだったので、その辺りも書いておきます

試験までにやったこと

  1. AWS 公式研修: Developing on AWSの受講
    • 試験前にポイントと各モジュール末の問題を復習
  2. AWS WEB問題集
    • 2周 & 模擬試験
  3. AWS公式 模擬試験
  4. 書籍で問題集を実施
  5. AWS公式 試験対策ワークショップ
  6. AWS公式研修: DevOps Engineering on AWSの受講
  7. 公式ドキュメントを読む

0. 事前の知識レベル

AWS認定

  • 先に取得したアソシエイト試験

  • Developing on AWS研修受講前の業務経験

    • 複数のサーバレスアプリケーションのPoCを経験
    • CloudFormationやS3、CloudFront、WAF、AWS SDK等を頻繁に利用
    • Codeシリーズはあまり使っていなかった(Github Actionsなどを活用)
    • PO/SCM等のマネジメント寄りの業務や、SPA開発とそのHosting環境構築等を担当していたため、バックエンド(API Gateway, Lambda, DynamoDB等)を自ら手を動かして実装する機会に恵まれなかった

1. Developing on AWSを受講

  • 概要

    • 日程: 3days
    • テキストはGlimoreでPDFを閲覧する。受講後も閲覧可能。試験前の学習にも役立つ。
    • プログラムからSDKでAWSのサービスを動かす
    • 前提知識
      • AWSのサービスの知識
      • Java, C# /.NET, Pythonの実務的な知識
  • 所感

    • 費用を出して貰える会社であれば、確実に受講すべき
    • 各サービスの概要は基本的に別のAWSの資格取得時に理解していたが、Labで本業のPJ内で扱えていないサービスを触れたことが非常に大きかったと感じる
    • 特にCodeシリーズやLambda, API Gateway, X-Rayは必ず一度は触った方がいい
    • 本業ではNode.jsを活用しているので、研修のLabがJava, C#, Python縛りなのは残念であった
    • 研修内で講師が教えてくれる試験のポイントは本当に重要
  • 上位の研修として以下がある

    • DevOps Engineering on AWS
    • Advanced Developing on AWS
  • 試験直前に講師が話していた試験頻出ポイントを復習

    • 例:DynamoDBのRCU/WCUの計算方法(計算問題は必ず出る)
  • 各モジュール末の問題も復習した方が良い

2. AWS WEB問題集サイトを2周

  • AWS問題集サイト
    • AWS認定の学習で最も有名なサイト
    • 有料なので課金が必要
    • 過去にSAA, SAP, SOAもこのサイトで学習
    • アップデートのタイミングには注意
      • サイトのアップデートと公式試験のアップデートのタイミングがかなり離れている時は注意
      • 公式試験が改訂される直前にこのサイトでSAPやSOAの学習をして、本番が改訂版で大分違うという経験があります…
    • 少なくとも2021/9月末時点のDeveloper 認定ではドンピシャでした
      • 不安があれば、後ほど紹介する書籍も使った方がいいです
    • 模擬試験モードもある
  1. 問題集

    • 各7問 x DVA#40をコツコツ実施
      • サイト内でも他の試験と比較して問題数が少ないので楽であった
    • ミスした問題をMarkdownでノートに整理
    • 合格者は2周している方が多い
    • 回答後に表示される解説まで読んで理解しなければ、試験では太刀打ちできない
    • 解説のリンクや分からなかった問題を調べた際に登場する公式のホワイトペーパーを読むほど合格に近づく
  2. AWS認定試験モード(AWS WEB問題集でできる模擬試験)

    • AWS認定デベロッパー - アソシエイトを受験
      • 試験時間:130分
      • 65問題
      • 合格点:720点
      • 問題ストック総数: 280問
    • 1周目終了時点
      • 57/65問 855/975点 (87.69%)
      • 残り1時間程度を残して終了。だらだら進めたので、サイトの前半の問題は忘れている状態
      • サイト利用者の平均点は93.85%

AWS公式模擬試験

  • 概要
    • 本番よりもかなり難しい
    • 料金: 2200円(税込み)
    • 所要時間: 35分
    • AWS Web問題集は非公式であるため、公式の問題傾向は確認しておくべき。ここで問題の傾向が著しく異なっていたら注意

申し込み手順

  • 公式サイト/試験のスケジュールを立てる

  • サインイン

  • アカウントへ移動

  • 新しい試験の予約

  • ピアソンVUEで模擬試験をスケジュールする

  • DVA-P01: AWS Certified Developer - Associate Practice

  • 申し込みが完了するとメールが届く

  • 試験開始ボタンの押下で試験前の説明画面に遷移する

    • 申し込んだ当日に好きなタイミングで受験可能
  • 引っかかった問題は試験中にメモして後に確認した

    • Cognitoオーソライザーについてなど、WEB問題集では登場しなかった問題もあった

結果

  • 30分のうち20分程度で完了

  • 合計スコア: 65%

  • トピックレベルのスコア:

    • 1.0. Deployment 50%
    • 2.0. Security 60%
    • 3.0. Development with AWS Services 67%
    • 4.0. Refactoring 100%
    • 5.0. Monitoring and Troubleshooting 67%
  • 以降の学習では点数が低いカテゴリに重点をおいた(書籍で問題集を解いた)

試験の予約

  • AWS認定サイト
  • AWS Certified Developer - Associate
    • PSIによるスケジュール or ピアソンVUEによるスケジュールを選択
  • 試験オプションの選択
    • テストセンター
    • オンライン
      • 今回はこちらを選択
  • 試験の準備
    • PCのシステムテストは必ず実施すべき(会社のPCでは無理でした)
    • onVUEというアプリをダウンロードする
    • このアプリが頻繁に固まることがあるので注意
  • 確認ができたら次へ
  • 試験言語/試験監督の言語を選択
  • 日付を選択

4. 書籍:ポケットスタディ AWS認定デベロッパーアソシエイト

  • ポケットスタディ AWS認定デベロッパーアソシエイト

    • 最近Developer Associate対策専用の書籍が初めて出版された
    • 試験前の週末に購入
    • 試験問題集 50問を実施
      • 解説が丁寧でかなり理解が深まった
    • 「1章 公式サンプル問題と問題傾向、解説」
    • 模擬試験で点数の低かったカテゴリ(展開、セキュリティ、開発)の章末問題も実施
      • 解説が丁寧で理解が深まった
  • AWS認定3試験対策という書籍もある

    • 私はSOA受験時に購入してすでにやっていたので、今回の試験のためには使わなかったが、SAAやSOAを取っていない方には必要かも

5. AWS公式 試験対策ワークショップ

  • 概要
    • 定期開催されており、よくAWSからメールで案内が来る
    • 無料
  • 会社で業務時間内に受けてOKと言われたので受講
  • 所感
    • 暇があれば受講推奨
    • 試験のポイントを解説してくれる
    • 受けなくとも勉強すれば合格はできる
  • 試験前に章末問題と模擬試験などで引っかかったカテゴリのスライドを確認

6. AWS公式研修: DevOps Engineering on AWSの受講

  • 上位の試験の研修をDVA試験前に受講
  • この研修までに受験しようと考えていたが、結果的にDVAの対策にもなった

オンラン試験本番

  • オンライン試験について
    • 試験の30分前がチェックイン時間
      • スマホで部屋中を撮影して回るなど結構面倒
      • チャット形式で試験監督と会話する
    • モニターにつなげてはならない
      • なるべく大画面のPCを用意すべき
    • 試験中に部屋に人が入ってはならない
      • 子供が入ってしまう環境は危険
    • 余計な操作をするとonVUEが何度も固まるので注意
      • Command + で文字サイズを変更しようとしたり、試験開始後にチャットを操作したら、この事象が発生した
      • 事前のシステムチェックでは全く問題なく、試験開始後に初めて発生した
      • 一度PCを再起動する羽目にもなった
        • メールで届いたURLから復帰はできた
      • 固まったり途中離脱した際にも時間は進んだ状態で再開する。0からやり直しはできない
      • フルスペックのMacBookProで他のAPを閉じていたため、マシンのスペックの問題ではない。もしかしたら、Bluetoothで繋げていたLogicoolのマウスが問題となっていたかもしれない。何も繋げない方が良さそう
    • 正直なところストレスフルで最悪のUXだった

結果

  • 60分ほど残して試験を完了
  • 無事合格
  • 忘れないうちにDevOps Professionalも受けてみようと思います

参考

関連記事

Amazon API Gateway WebSocket APIでリアルタイム通信を行うチャットAPを開発 [SAR/SAM]

  • リアルタイムの双方向通信を可能にするAmazon API Gateway WebSocket APIについてのメモ
    • 活用例: チャットアプリ、金融取引システム
  • リアルタイムの双方向通信にはAppSyncを活用する手もあるが、条件によっては使えないことがあった(個人的にはAmplifyでAppSyncを自動生成するのが一番楽だと思います)
  • 下記はAWSブログで公開されていたリアルタイムチャットAPの開発方法とGithubに公開されているSAMテンプレートの内容の個人的理解のまとめ

Amazon API Gateway WebSocket API

WebSocketAPIとは

  • Amazon API Gatewayには以下の3種のタイプがある

    • HTTP API
    • REST API
    • WebSocket API
  • WebSocket API

    • リアルタイムでの双方向通信に用いられるAPIタイプ
    • 公式説明
      1
      2
      チャットアプリケーションやダッシュボードなど、リアルタイムのユースケース向けの永続的な接続を使用する WebSocket API を構築します。
      双方向の振る舞いにより、クライアント/サーバーとのやりとりがより豊富になります。これは、明示的なリクエストをする必要のないクライアントにデータをプッシュできるためです。 WebSocket APIは、チャットアプリケーション、コラボレーションプラットフォーム、マルチプレイヤーゲーム、金融取引プラットフォームなどのリアルタイムアプリケーションでよく使用されます。
  • 従来WebSocket APIを構築するためには、WebSocketプロトコルの基礎となる永続的な接続の管理を担当するホストの設定が必要であったが、API Gateway Web Socket APIであれば、こういった作業をショートカットできる

WebSocket APIの概念

  • ルート
    • 新しいリソースタイプ
      1
      ルートは、API Gatewayが特定のタイプのクライアントリクエストを処理する方法を記述し、ルートを識別するために提供する値であるrouteKeyパラメータを含みます。
    • WebSocket APIは1つまたは複数のルートで構成される
      1
      WebSocket APIは、1つまたは複数のルートで構成されています。特定のインバウンドリクエストで使用するルートを決定するには、ルートセレクションエクスプレッション(選択式)を指定します。式は、ルートのrouteKey値の1つに対応する値を生成する着信リクエストに対して評価されます。
  • API Gatewayでルートに使用できる3つの特別なrouteKey値
    • $default
      1
      選択式がAPIルート内の他のrouteKeyに一致しない値を生成する場合に使用されます。 これは、例えば、一般的なエラー処理メカニズムを実装するために使用できます。
    • $connect
      1
      クライアントがWebSocket APIに最初に接続するときに、関連するルートが使用されます。
    • $disconnect
      1
      クライアントがAPIから切断すると、関連するルートが使用されます。 この呼び出しは、ベストエフォート方式で行われます。

構築手順

開発サンプル:リアルタイムチャットAP

WebSocket Chat App Architecture

  • WebSocket APIとAPI Gatewayを使用してサーバーレスのリアルタイムチャットAPを構築する

  • 主な機能

    • クライアントはWebSocket APIに接続するときにチャットルームに参加
    • バックエンドは、ユーザーがWebSocket APIに接続した後に提供されるコールバックURLを使用して、特定のユーザーにメッセージを送信できる
    • ユーザーはルームにメッセージを送信できる
    • 切断されたクライアントはチャットルームから削除される
  • ロジック概要

    1
    アプリケーションは、クライアントとサーバー(1)間の接続を処理するAPI GatewayのWebSocket APIで構成されています。 クライアントがAPIに接続(2)または切断(5)すると、2つのAWS Lambdaが反応します。 sendMessage関数(3)は、クライアントがサーバーにメッセージを送信するときに呼び出されます。 サーバーは、新しいAPI Gateway管理APIを使用して、接続されているすべてのクライアント(4)にメッセージを送信します。 接続された各クライアントを追跡するには、DynamoDBテーブルを使用して接続識別子を保持します。
  • 構築方法は3つあったので全て試した

    • 手動でAWS Consoleから構築
    • AWS Serverless Application Repository(SAR)のsimple websocket-chat-appを実行
      • SARであればボタン一つで自動構築できる。SAMのテンプレートがAP単位で公開されている
      • 今回のチャットAPの一式(Lambda関数、DynamoDBテーブル定義、IAMロールなど)が提供されている
    • SAM(Serverless Application Model)テンプレートをSAM CLIで実行
      • GitHubリポジトリにSARで使われているテンプレートが公開されている
      • 上記のリポジトリを手元にCloneしてSAM CLIで実行する
  • AmplifyではWebSocket APIはまだ使えないっぽい(2021/08/20時点)

SAMテンプレート

  • SAM CLIを用いると以下のテンプレートで環境を自動生成できる

    • オリジナルのWebSocket APIを開発する際もここから改変すると楽そう
    • ParameterはDynamoDBのテーブル名のみ
    • 内容の説明は以降のコンソールでの実装手順と一緒にまとめた
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      AWSTemplateFormatVersion: '2010-09-09'
      Transform: AWS::Serverless-2016-10-31
      Description: >
      simple-websockets-chat-app
      SAM Template for simple-websockets-chat-app that has the DynamoDB table and Lambda
      functions needed to demonstrate the Websocket protocol on API Gateway.
      Parameters:
      TableName:
      Type: String
      Default: 'simplechat_connections'
      Description: (Required) The name of the new DynamoDB to store connection identifiers for each connected clients. Minimum 3 characters
      MinLength: 3
      MaxLength: 50
      AllowedPattern: ^[A-Za-z_]+$
      ConstraintDescription: 'Required. Can be characters and underscore only. No numbers or special characters allowed.'

      Resources:
      SimpleChatWebSocket:
      Type: AWS::ApiGatewayV2::Api
      Properties:
      Name: SimpleChatWebSocket
      ProtocolType: WEBSOCKET
      RouteSelectionExpression: "$request.body.action"
      ConnectRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: $connect
      AuthorizationType: NONE
      OperationName: ConnectRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref ConnectInteg
      ConnectInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Connect Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnConnectFunction.Arn}/invocations
      DisconnectRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: $disconnect
      AuthorizationType: NONE
      OperationName: DisconnectRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref DisconnectInteg
      DisconnectInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Disconnect Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnDisconnectFunction.Arn}/invocations
      SendRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: sendmessage
      AuthorizationType: NONE
      OperationName: SendRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref SendInteg
      SendInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Send Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SendMessageFunction.Arn}/invocations
      Deployment:
      Type: AWS::ApiGatewayV2::Deployment
      DependsOn:
      - ConnectRoute
      - SendRoute
      - DisconnectRoute
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Stage:
      Type: AWS::ApiGatewayV2::Stage
      Properties:
      StageName: Prod
      Description: Prod Stage
      DeploymentId: !Ref Deployment
      ApiId: !Ref SimpleChatWebSocket
      ConnectionsTable:
      Type: AWS::DynamoDB::Table
      Properties:
      AttributeDefinitions:
      - AttributeName: "connectionId"
      AttributeType: "S"
      KeySchema:
      - AttributeName: "connectionId"
      KeyType: "HASH"
      ProvisionedThroughput:
      ReadCapacityUnits: 5
      WriteCapacityUnits: 5
      SSESpecification:
      SSEEnabled: True
      TableName: !Ref TableName
      OnConnectFunction:
      Type: AWS::Serverless::Function
      Properties:
      CodeUri: onconnect/
      Handler: app.handler
      MemorySize: 256
      Runtime: nodejs12.x
      Environment:
      Variables:
      TABLE_NAME: !Ref TableName
      Policies:
      - DynamoDBCrudPolicy:
      TableName: !Ref TableName
      OnConnectPermission:
      Type: AWS::Lambda::Permission
      DependsOn:
      - SimpleChatWebSocket
      Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref OnConnectFunction
      Principal: apigateway.amazonaws.com
      OnDisconnectFunction:
      Type: AWS::Serverless::Function
      Properties:
      CodeUri: ondisconnect/
      Handler: app.handler
      MemorySize: 256
      Runtime: nodejs12.x
      Environment:
      Variables:
      TABLE_NAME: !Ref TableName
      Policies:
      - DynamoDBCrudPolicy:
      TableName: !Ref TableName
      OnDisconnectPermission:
      Type: AWS::Lambda::Permission
      DependsOn:
      - SimpleChatWebSocket
      Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref OnDisconnectFunction
      Principal: apigateway.amazonaws.com
      SendMessageFunction:
      Type: AWS::Serverless::Function
      Properties:
      CodeUri: sendmessage/
      Handler: app.handler
      MemorySize: 256
      Runtime: nodejs12.x
      Environment:
      Variables:
      TABLE_NAME: !Ref TableName
      Policies:
      - DynamoDBCrudPolicy:
      TableName: !Ref TableName
      - Statement:
      - Effect: Allow
      Action:
      - 'execute-api:ManageConnections'
      Resource:
      - !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SimpleChatWebSocket}/*'
      SendMessagePermission:
      Type: AWS::Lambda::Permission
      DependsOn:
      - SimpleChatWebSocket
      Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref SendMessageFunction
      Principal: apigateway.amazonaws.com

      Outputs:
      ConnectionsTableArn:
      Description: "Connections table ARN"
      Value: !GetAtt ConnectionsTable.Arn

      OnConnectFunctionArn:
      Description: "OnConnect function ARN"
      Value: !GetAtt OnConnectFunction.Arn

      OnDisconnectFunctionArn:
      Description: "OnDisconnect function ARN"
      Value: !GetAtt OnDisconnectFunction.Arn

      SendMessageFunctionArn:
      Description: "SendMessage function ARN"
      Value: !GetAtt SendMessageFunction.Arn

      WebSocketURI:
      Description: "The WSS Protocol URI to connect to"
      Value: !Join [ '', [ 'wss://', !Ref SimpleChatWebSocket, '.execute-api.',!Ref 'AWS::Region','.amazonaws.com/',!Ref 'Stage'] ]
  • Resourceのまとめ

    • AWS::ApiGatewayV2::Api x 1
    • RouteとIntegration x 3セット
      • AWS::ApiGatewayV2::Route x 3
      • AWS::ApiGatewayV2::Integration x 3
    • デプロイ関係
      • AWS::ApiGatewayV2::Deployment x 1
      • AWS::ApiGatewayV2::Stage
    • AWS::DynamoDB::Table x 1
    • Lambda関数と権限 x 3セット
      • AWS::Serverless::Function x3
      • AWS::Lambda::Permission x 3

WebSocket APIの作成(コンソールからの構築手順)

コンソールでポチポチする場合は先にLambda関数を作ったほうが手間が少ない
コンソールでの構築手順とテンプレートの該当箇所を以下に示す

  • AWS Console/API Gateway/APIを作成

  • APIタイプを選択

    • WebSocketAPIの”構築”を押下
  • Step1 APIの詳細を指定する

    • API名
      • ex. My Chat API
    • ルート選択式
      • ex. $ request.body.action
      • ルート選択式の値で記述された属性は、クライアントがAPIに送信するすべてのメッセージに存在する必要がある。リクエストメッセージの例↓
        1
        2
        3
        4
        {
        "action": "sendmessage",
        “data”: "Hello, I am using WebSocket APIs in API Gateway.”
        }
      • WebSocket APIは、メッセージの内容に基づいてメッセージをルーティングするために、ルーティングキーとして機能するJSON形式のメッセージを必要とする
    • 次へ
  • Step1の設定内容はSAMテンプレートの以下に該当する

    1
    2
    3
    4
    5
    6
    SimpleChatWebSocket:
    Type: AWS::ApiGatewayV2::Api
    Properties:
    Name: SimpleChatWebSocket
    ProtocolType: WEBSOCKET
    RouteSelectionExpression: "$request.body.action"
  • Step2 ルートを追加

    • $connectや$disconnectなどは事前定義されている
    • カスタムルート
      • “カスタムルートを追加”
        • こちらから独自のルートを作成する
      • ルートキーを入力
        • ex: sendmessage
    • 次へ
  • Step3 統合をアタッチする

    • 公式説明
      1
      この API をデプロイするには、少なくとも 1 つのルートを設定する必要があります。設定するすべてのルートに統合がアタッチされている必要があります。後で統合をセットアップするには、ルートの統合タイプとして [Mock] を選択します。
    • 統合タイプ
      • 以下がある
        • Mock, Lambda, HTTP, AWSのサービス VPCリンク
      • 今回はLambda
        • 既存のLambdaを選択
        • 先に作成しておく必要がある
      • Mock
        • 後で統合する場合はMockを選択
    • 次へ
  • Step2,3の設定事項(Route/Integration)はSAMの以下に該当する

    • RouteとIntegarationはセット(今回は3セット)
    • IntegrationでLambdaとの紐づけを行っている
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      ConnectRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: $connect
      AuthorizationType: NONE
      OperationName: ConnectRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref ConnectInteg
      ConnectInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Connect Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnConnectFunction.Arn}/invocations
      DisconnectRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: $disconnect
      AuthorizationType: NONE
      OperationName: DisconnectRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref DisconnectInteg
      DisconnectInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Disconnect Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnDisconnectFunction.Arn}/invocations
      SendRoute:
      Type: AWS::ApiGatewayV2::Route
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      RouteKey: sendmessage
      AuthorizationType: NONE
      OperationName: SendRoute
      Target: !Join
      - '/'
      - - 'integrations'
      - !Ref SendInteg
      SendInteg:
      Type: AWS::ApiGatewayV2::Integration
      Properties:
      ApiId: !Ref SimpleChatWebSocket
      Description: Send Integration
      IntegrationType: AWS_PROXY
      IntegrationUri:
      Fn::Sub:
      arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SendMessageFunction.Arn}/invocations
  • Step4 ステージを追加

    1
    ステージは、API をデプロイできる個別に設定可能な環境です。API 設定の変更を有効にするには、ステージにデプロイする必要があります。開発や本稼働などの環境を表すステージを追加できます。
    • ステージ名
      • 任意のステージ名を定義
      • ex: Prod, dev
    • 次へ
  • SAMテンプレートでは以下のResourceが該当する

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Deployment:
    Type: AWS::ApiGatewayV2::Deployment
    DependsOn:
    - ConnectRoute
    - SendRoute
    - DisconnectRoute
    Properties:
    ApiId: !Ref SimpleChatWebSocket
    Stage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
    StageName: Prod
    Description: Prod Stage
    DeploymentId: !Ref Deployment
    ApiId: !Ref SimpleChatWebSocket
  • Step5 作成してデプロイ

    • 内容を確認して”作成してデプロイ”を押下
    • ルートやステージが生成される
  • SAMテンプレートでは、ここまでの設定の他にLambda関数や実行環境、DynamoDBテーブルなどが定義されていた

  • 残りのResourceの詳細

    • AWS::DynamoDB::Table x 1
    • Lambda関数と権限 x 3セット
      • AWS::Serverless::Function x3
      • AWS::Lambda::Permission x 3

Lambda関数の構築(コンソールから)

  • コンソールから作る場合

    • Console/Lambda/関数の作成
    • sendMessage, onConnect, onDisconnectで関数を生成。コードスニペットを貼り付けてdeploy
  • コードスニペットはGitを参照

    • sendMessage関数
      • この関数は、クライアントの1つが送信したデータを受け取り、現在接続されているすべてのクライアントを検索し、それぞれに提供されたデータを送信する
    • onConnect関数
      • requestContextからのconnectionId値をDynamoDBテーブルに挿入する
    • onDisconnect関数
      • 指定されたconnectionId値に対応するレコードを削除
  • 手動の場合はAPI Gatewayとの統合と権限設定も必要

    • API GW.MychatAPI/ルート/各ルート/統合
      • 統合タイプ: Lambda関数として作成した関数を選択
  • SAMテンプレートでは以下のように表現される

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
ConnectionsTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: "connectionId"
AttributeType: "S"
KeySchema:
- AttributeName: "connectionId"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
SSESpecification:
SSEEnabled: True
TableName: !Ref TableName
OnConnectFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: onconnect/
Handler: app.handler
MemorySize: 256
Runtime: nodejs12.x
Environment:
Variables:
TABLE_NAME: !Ref TableName
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TableName
OnConnectPermission:
Type: AWS::Lambda::Permission
DependsOn:
- SimpleChatWebSocket
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref OnConnectFunction
Principal: apigateway.amazonaws.com
OnDisconnectFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ondisconnect/
Handler: app.handler
MemorySize: 256
Runtime: nodejs12.x
Environment:
Variables:
TABLE_NAME: !Ref TableName
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TableName
OnDisconnectPermission:
Type: AWS::Lambda::Permission
DependsOn:
- SimpleChatWebSocket
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref OnDisconnectFunction
Principal: apigateway.amazonaws.com
SendMessageFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: sendmessage/
Handler: app.handler
MemorySize: 256
Runtime: nodejs12.x
Environment:
Variables:
TABLE_NAME: !Ref TableName
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref TableName
- Statement:
- Effect: Allow
Action:
- 'execute-api:ManageConnections'
Resource:
- !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SimpleChatWebSocket}/*'
SendMessagePermission:
Type: AWS::Lambda::Permission
DependsOn:
- SimpleChatWebSocket
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref SendMessageFunction
Principal: apigateway.amazonaws.com

SAR(Serverless Application Repository)で自動構築

  • SARにも今回の環境のテンプレートが公開されており、自動構築できる

  • 以下にアクセス

  • “Deploy”

  • 自分のAWSアカウントの確認画面で”デプロイ”

  • 以下のメッセージが表示された

    1
    承認が必要です。デプロイするには、[アプリケーション設定] セクションのチェックボックスをオンにしてください。
  • 該当箇所をチェック

    1
    このアプリがカスタム IAM ロールとリソースポリシーを作成することを承認します
  • デプロイを押下

  • Lambda/アプリケーションで生成されたAPスタックを確認することができる

  • 生成されていたリソース

    • DynamoDBテーブル: simplechat_connectionsはconnectionIdのみを保持する
    • API GW: SimpleChatWebSocket
      • $connect, $disconnect, sendMessageの3ルート
      • ダッシュボードからWebSocket URLを確認することができる
    • Lambda関数

      SAMテンプレートで自動構築

  • SAM CLIを使えば、SAMテンプレートで今回の構成を構築することもできる

    • SARでは裏側でSAMテンプレートを使っている
  • 今回のチャットAPのSAM Template手元にクローンしてCLIから実行する

### WebSocketAPIの検証/検証ツール wscat

  • WebSocket APIのテストには、OSSのコマンドラインツール wscatが役立つ
  1. NPMをインストールします。
  2. wscatをインストール
    1
    $ npm install -g wscat
  3. コンソールで、次のコマンドを実行して公開APIエンドポイントに接続します。
    • AWS Cnsole/API Gateway/My Chat APIのダッシュボードでWeb Socket URLとして下記のURLを確認出来る
      1
      2
      $ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/{STAGE}
      Bash
  4. sendMessage関数をテストするには、次の例のようなJSONメッセージを送信する。 Lambda関数はコールバックURLを使用してそれを返す:
    1
    2
    3
    4
    $ wscat -c wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/dev
    connected (press CTRL+C to quit)
    > {"action":"sendmessage", "data":"hello world"}
    < hello world
  • wscatを複数のコンソールで実行すると、それぞれが “hello world”を受信する。これで、WebSocket APIからメッセージを送信したり、応答を返すことができるようになったと言える
  • この検証方法は今回のサンプル以外でも使えそう

参考

関連記事

その他

@EventEmitter @Input @Output @ViewChild ACM AMP API Gateway AR AR.js AR.js Studio AWS AWS Amplify AWS Budgets AWS Cost Explorer AWS SDK for JavaScript AddThis Adobe XD Alexa Amazon CloudWatch Amazon Honycode Amazon SNS Android Angular Angular Material AngularFire AppSync Augury C CDN CI/CD Cloud Craft Cloud9 CloudFormation CloudFront CloudTrail Cognito Cost Anomaly Detection Cubase ai Cubasis LE DTM Disqus DynamoDB Elgato HD 60S Firebase Firebase Hosting Former2 Github Github Actions Github.com GithubEnterprise GithubPages Google Chrome Google Cloud Shell GraphQL Hexo Hosting IAM Ionic JSON JavaScript LadioCast Logging LowCode MFA MS Authentication MacBook Pro 16 Mind Node NETDUETTO Netflix Party Netlify Network NoCode Observable PO PdM Promise RPA ReactiveForm Recognition Route53 S3 SAM(Serverless Application Model) SAR SSL SYNCROOM Schematics ScrumInc Serverless Service Siri Sitemap Spark AR Steinberg UR44C Teams Touch Cast Studio Treetable TypeScript UI UI Bakery WAF WAFv2 WEB Page Dev WEB会議 WebAR WebSocketAPI Webhook Windows Power Automate Wireshark aot async/await aws config cloud9 display.land draw.io e2e test filter() forkJoin() google search console hexo-generator-amp iOS iPad Pro iPhone icarus map() mat input mat tree mat-checkbox mat-input mat-selection-list mmhmm ngFor plantUML popIn Aladdin2 then() vscode ”global is not defined” らくがきAR アジャイル アジャイル開発 クロスプラットフォーム ショートカット スクラム スクラム開発 テレワーク ファイル操作 ブラウザ型IDE プロダクトオーナー プロダクトマネージャー プロトタイピング リモートセッション 共同開発 双方向データバインディング 待ち合わせ処理 認定スクラムマスター 静的WEB Hosting 静的WEBサイトHosting
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×