Upgrade to Pro — share decks privately, control downloads, hide ads and more …

生配信管理システムのバックエンド〜AWS AppSyncで迅速に構築するGraphQLサービス...

生配信管理システムのバックエンド〜AWS AppSyncで迅速に構築するGraphQLサービス〜 / Backend of live streaming management system - GraphQL service to build quickly with AWS AppSync

Yusei Yamanaka

December 15, 2021
Tweet

More Decks by Yusei Yamanaka

Other Decks in Programming

Transcript

  1. 1

  2. 2 山中勇成 a.k.a みゆっき
 株式会社サイバーエージェント 2017年 新卒入社 
 株式会社AbemaTV 開発局

    コンテンツ配信Div. 
 未踏スーパークリエータ
 最近の 買い 欲しい物
 自己紹介 Panasonic 4Kリモートカメラ 
 AW-UE150

  3. SUPERBIRDにより、配信用のオペレーションツールのバックエンドを作り直す必要があった。 
 今回話す内容について 5 課題
 Streaming Server Encoder Manifest Decorator

    この辺りのステータス表示や制御を行うためのツール 
 • コンテンツ配信チームでは、現状2人でABEMAの配信を見ているため、 
 できるだけメンテナンスコストを減らしたい
 • 他の新規案件や改修タスクもあるため、 できるだけ短時間で構築したい
 • スキルアップを目的に流行りのツールを使ってみたい

  4. GraphQLとは 
 
 
 Facebookにより開発された、WebAPIのためのクエリ言語とそのランタイム
 https://graphql.org/
 
 • 少ないリクエストで複数のリソースにアクセス可能 


    • クライアントに必要な最小限のデータだけを取得可能 
 
 • エンドポイントがリソースやアクションを表していないため、 
 キャッシュやモニタリングなど、HTTPのエコシステムを活用しにくい 
 7 Pros
 Cons

  5. 8 schema { query: Query } type Query { getUser(id:

    Int!): Person } type Person { id: Int! name: String! age: Int! job: String children: [Person!]! } Schema { "getUser": { "name": "Luke Skywalker", "job": "driver", "age": 56, "children": [ { "name": "Giselle Skywalker", "age": 24, "job": "engineer" }, { "name": "Sania Calhoun", "age": 12, "job": null } ] } } Response { getUser(id: 1) { name age job children { name age job } } } Request GraphQLのスキーマとリクエストの流れ
  6. 
 
 
 完全マネージド型のGraphQLサーバー
 https://aws.amazon.com/jp/appsync/
 • DynamoDBやLambdaなどのデータソースと接続し、リクエストを処理可能 
 • 認証やキャッシュ、リアルタイムのサブスクリプション、クライアントSDKと

    
 連携すればオフラインでの利用なども可能 
 • APIリクエストのボリュームに合わせた GraphQL API 実行エンジンの自動的なスケールアッ プとダウンが行われる
 AWS AppSyncとは 9 AWS AppSync

  7. AWS AppSyncのアーキテクチャ AppSyncでは、予め設定されたスキーマとリゾルバーを元にデータソースへアクセスを行い、クライ アントにデータを返却する。
 10 DynamoDB Aurora Lambda AppSync Client

    Schema Resolver Cognito Data Source 現時点で対応しているデータソース 
 • DynamoDB
 • AWS Lambda
 • Amazon OpenSearch Service 
 • HTTP
 • Aurora Serverless
 HTTP
  8. 
 スキーマのフィールドを解決するための設定 
 データソースとマッピングテンプレートを指定する。 
 
 データソースとのリクエストとレスポンスをどう処理するか を記述する。
 テンプレートは、ApacheVTLで記述する。 


    リクエストテンプレートは、JSON形式で出力することが多 い。
 11 GraphQL Request Resolver Request Mapping Template Response Mapping Template Data Source GraphQL Response リゾルバーとマッピングテンプレート リゾルバー
 マッピングテンプレート 

  9. 12 schema { query: Query } type Query { getUser(id:

    Int!): Person } type Person { id: Int! name: String! age: Int! job: String children: [Person!]! } Schema Resolver { "version": "2017-02-28", "operation": "GetItem", "key": { "id": $util.dynamodb.toDynamoDBJson($ctx.args.id), } } DataSource UserTable Request Mapping Template - DataSourceにどういうクエリを送るか Response Mapping Template - DataSourceから返ってきたデータをどうクライアントに返すか $util.toJson($ctx.result) {"N": "1234"} Query.getUserにリゾルバーを紐付け
 リゾルバーとマッピングテンプレートの紐付け
  10. AWS AppSyncをどの様に使うか 13 Lambda DynamoDB AppSync S3 Operators Cognito •

    AppSyncは、GraphQLのゲートウェイ (認証とフィールドの解決) 、DynamoDBへの取得系クエリ の処理を行う様に設定
 • 上記以外の更新系などの処理は、AppSyncからLambdaを呼び出している 
 ➡ 更新時には、バリデーションや外部APIの呼び出しなどを行う可能性が高いため、 
 処理の柔軟性が高いLambdaを前提として構築した 

  11. AWS AppSyncの良い点・悪い点 
 • スケーラブルなマネージドGraphQLサーバが簡単に作れる 
 • クライアントSDKを使用すれば認証やオフラインキャッシュなども利用可能 
 


    • 細かいことをやろうとするとLambdaが必要になる 
 • テストがしにくい
 • マッピングテンプレート(Apache VTL)を覚える必要がある 
 • バリデーションや認可などをマッピングテンプレートに書くことができるが、 
 管理が複雑になる
 15 Pros
 Cons

  12. 社内では、Terraformを用いてAWSリソースを管理することが一般的。 
 ただし、それではAppSyncのスキーマ変更やLambdaのコード変更の度にTerraformの反映が必要 になってしまう。
 AWS AppSyncをどのように構築するか 16 CodeBuild Cognito DynamoDB

    S3 SQS IAM Roles Terraformで生成されるリソース 
 Serverlessで生成されるリソース 
 Lambda AppSync ➡ 基本はTerraform、開発利便性が必要なリソースはServerlessで管理するように 

  13. 
 
 
 サーバレスコンポーネントのために開発された構成管理ツール
 https://www.serverless.com/ 
 • AWS Lambdaなどのサーバレスコンポーネントが簡単に構築、管理可能 


    • 様々なProvider(AWS, GCP, Azure, etc...)に対応している
 • CloudFormationのテンプレートを記述すれば対応外のものも管理可能 
 • プラグインを開発することにより、ビルドや更新時の挙動を変更可能 
 Serverless Frameworkとは 17
  14. Serverlessの実行環境には、CodeBuildを使用。 
 ➡ AWS内のリソースを管理するため、IAM Roleベースで権限を管理したいため 
 Serverlessの実行環境 18 CodeBuild GitHub

    コードリポジトリ Post Webhook Lambda AppSync dependent go modules... GitHub Token Run Setup Webhook Goの依存モジュールなどのアクセスについては、GitHubのTokenをParameter Storeで管理。

  15. GitHub Flowを採用し、開発環境ではdevelopブランチを自動的に反映、本番環境はmasterブランチ を自動的に反映する様にCodeBuildで設定を行っている。 
 
 
 
 
 
 


    ➡ 検証したい場合は、開発環境などでブランチを指定して ビルドすることにより構成が反映される 
 ServerlessのCD 19
  16. • Serverlessのテンプレートは、TypeScriptで記述 
 • Lambdaは、単一のバイナリではなく、GraphQLのフィー ルド毎にバイナリを生成
 • ServerlessでAppSyncを管理するために、 serverless-appsync-pluginを使用 


    • ServerlessでGoのLambdaデプロイをするのに、 serverless-go-pluginを使用
 ◦ 右の様なモノレポなプロジェクトをデプロイ可能 
 
 Serverlessの構成 20 ├── serverless.ts ├── functions │ ├── core │ │ ├── hoge │ │ │ └── hoge.go │ │ ├── foo │ │ │ └── foo.go │ │ ├── go.mod │ │ └── go.sum │ ├── update-live-stream │ │ ├── main.go │ │ ├── go.mod │ │ └── go.sum │ ├── update-encoder │ │ ├── main.go │ │ ├── go.mod │ │ └── go.sum │ │── update-pipeline │ │ ├── main.go │ │ ├── go.mod │ │ └── go.sum プロジェクトのディレクトリ構成 共通ロジック 関数A 関数B 関数C
  17. バックエンドアーキテクチャ 21 CodeBuild GitHub コードリポジトリ Post Webhook Lambda DynamoDB AppSync

    GitHub Terraformリポジトリ Push IAM Roles For CodeBuild / AppSync / Lambda / SQS S3 Manage&Deploy Request Other services in EKS Push Other services in GKE Service A Service B Service D Service C dependent go modules... Release GitHub Token SQS Operators Developers Put Run Setup Webhook Appliance Datacenter Cognito
  18. • Lambdaの起動時間が許容できない 
 ◦ リクエスト時間がシビアな処理(=CM挿入処理)をLambdaで捌こうと思ったが、AppSync経由で Lambdaからの応答が返ってくる時間が許容できなかった 
 ◦ Provisioned ConcurrencyなLambdaを設定したが、Provisionedでない呼び出しの

    
 タイミングが許容できない 
 ◦ Lambda自体の起動というより、アプリケーションの初期化 (DnyamoDBへのTLS接続など) に
 時間を要していた
 AWS AppSyncを使って直面した課題1 22 ➡ EKS上にCM挿入処理を切り出したアプリケーションを用意し、AppSyncからHTTPを データソー スとして呼び出すようにした
 

  19. ➡ AppSyncへのリクエストに用いられる Authorization ヘッダーをバイパスして、HTTP側で Cognito のJWTを検証するようにした 
 • HTTPデータソースの呼び出し元がAppSyncであることを検証できない 


    ◦ HTTP側でAppSyncから呼び出した事が保証できないと、セキュリティ上の懸念がある 
 AWS AppSyncを使って直面した課題2 23 Lambda AppSync Operators HTTP Server on EKS Authorization: ... Authorization: ...
  20. AWS AppSyncを使って直面した課題3 • 障害や問題発生時に、CloudWatchのログのみだと切り分けが難しい 
 ◦ AppSyncへのリクエスト時にCloudWatchに保存されるログは、事象ベースからの検索のハードル が高い
 ◦ 問い合わせがあった時間から、AWS

    AppSyncへのリクエストを検索し、判明したRequestIdや X-Amzn-Trace-Idなどを元に、各種コンポーネントの調査を行う 
 24 ➡ トレースを行いやすくするツール開発の検討、クライアント側への情報表示の検討 

  21. まとめ • AWS AppSyncとServerless Frameworkを使うことで、マネージドなGraphQLサーバーを短時間 で構築することができた
 ◦ 実際、構築と開発にかかった期間は、ロジック部分も含めて3ヶ月ほど 
 •

    AWS AppSyncでは、取得系はDynamoDB、更新系はLambdaをデータソースにしている 
 ◦ 一部、Lambdaで許容できない処理はHTTPを呼び出すことで解決 
 • 構成はGitHub Flowで管理していて、ブランチへのpushをトリガーに自動的に構成が反映され る
 
 26
  22. 28