Share
Embed
生配信管理システムのバックエンド〜AWS AppSyncで迅速に構築するGraphQLサービス〜 / Backend of live streaming management system - GraphQL service to build quickly with AWS AppSync
Yusei Yamanaka
December 15, 2021
Transcript
28 slides
-
2 山中勇成 a.k.a みゆっき 株式会社サイバーエージェント 2017年 新卒入社 株式会社AbemaTV 開発局
コンテンツ配信Div. 未踏スーパークリエータ 最近の 買い 欲しい物 自己紹介 Panasonic 4Kリモートカメラ AW-UE150 -
SUPERBIRDについて 4 中央集約(ハブ化) エンコーダーリプレイス 監視設備強化 新配信管理画面 各スタジオとデータセンターを専用線で、 データセンターとクラウドをプライベートピアで接続 品質の高いアプライアンス型の 専用エンコーダーの導入
電源や回線が冗長化され、 レガシーな監視から脱却された 新しい監視設備を構築 現場の意見をヒアリングした上 で、現場が使いやすい管理画面を 新たに開発 -
SUPERBIRDにより、配信用のオペレーションツールのバックエンドを作り直す必要があった。 今回話す内容について 5 課題 Streaming Server Encoder Manifest Decorator
この辺りのステータス表示や制御を行うためのツール • コンテンツ配信チームでは、現状2人でABEMAの配信を見ているため、 できるだけメンテナンスコストを減らしたい • 他の新規案件や改修タスクもあるため、 できるだけ短時間で構築したい • スキルアップを目的に流行りのツールを使ってみたい -
GraphQLとは Facebookにより開発された、WebAPIのためのクエリ言語とそのランタイム https://graphql.org/ • 少ないリクエストで複数のリソースにアクセス可能
• クライアントに必要な最小限のデータだけを取得可能 • エンドポイントがリソースやアクションを表していないため、 キャッシュやモニタリングなど、HTTPのエコシステムを活用しにくい 7 Pros Cons -
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のスキーマとリクエストの流れ -
完全マネージド型のGraphQLサーバー https://aws.amazon.com/jp/appsync/ • DynamoDBやLambdaなどのデータソースと接続し、リクエストを処理可能 • 認証やキャッシュ、リアルタイムのサブスクリプション、クライアントSDKと
連携すればオフラインでの利用なども可能 • APIリクエストのボリュームに合わせた GraphQL API 実行エンジンの自動的なスケールアッ プとダウンが行われる AWS AppSyncとは 9 AWS AppSync -
AWS AppSyncのアーキテクチャ AppSyncでは、予め設定されたスキーマとリゾルバーを元にデータソースへアクセスを行い、クライ アントにデータを返却する。 10 DynamoDB Aurora Lambda AppSync Client
Schema Resolver Cognito Data Source 現時点で対応しているデータソース • DynamoDB • AWS Lambda • Amazon OpenSearch Service • HTTP • Aurora Serverless HTTP -
スキーマのフィールドを解決するための設定 データソースとマッピングテンプレートを指定する。 データソースとのリクエストとレスポンスをどう処理するか を記述する。 テンプレートは、ApacheVTLで記述する。
リクエストテンプレートは、JSON形式で出力することが多 い。 11 GraphQL Request Resolver Request Mapping Template Response Mapping Template Data Source GraphQL Response リゾルバーとマッピングテンプレート リゾルバー マッピングテンプレート -
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にリゾルバーを紐付け リゾルバーとマッピングテンプレートの紐付け -
AWS AppSyncをどの様に使うか 13 Lambda DynamoDB AppSync S3 Operators Cognito •
AppSyncは、GraphQLのゲートウェイ (認証とフィールドの解決) 、DynamoDBへの取得系クエリ の処理を行う様に設定 • 上記以外の更新系などの処理は、AppSyncからLambdaを呼び出している ➡ 更新時には、バリデーションや外部APIの呼び出しなどを行う可能性が高いため、 処理の柔軟性が高いLambdaを前提として構築した -
AWS AppSyncのデバッグ方法 14 リクエスト毎にリゾルバーがどう処理され たかをログとして出力 CloudWatch リクエスト毎にリクエストの詳細やデータ ソースへのアクセスを分析
X-Ray ブラウザ上で簡単にGraphQLクエリを実 行可能(Cognitoの認証も可能) コンソール -
AWS AppSyncの良い点・悪い点 • スケーラブルなマネージドGraphQLサーバが簡単に作れる • クライアントSDKを使用すれば認証やオフラインキャッシュなども利用可能
• 細かいことをやろうとするとLambdaが必要になる • テストがしにくい • マッピングテンプレート(Apache VTL)を覚える必要がある • バリデーションや認可などをマッピングテンプレートに書くことができるが、 管理が複雑になる 15 Pros Cons -
社内では、Terraformを用いてAWSリソースを管理することが一般的。 ただし、それではAppSyncのスキーマ変更やLambdaのコード変更の度にTerraformの反映が必要 になってしまう。 AWS AppSyncをどのように構築するか 16 CodeBuild Cognito DynamoDB
S3 SQS IAM Roles Terraformで生成されるリソース Serverlessで生成されるリソース Lambda AppSync ➡ 基本はTerraform、開発利便性が必要なリソースはServerlessで管理するように -
サーバレスコンポーネントのために開発された構成管理ツール https://www.serverless.com/ • AWS Lambdaなどのサーバレスコンポーネントが簡単に構築、管理可能
• 様々なProvider(AWS, GCP, Azure, etc...)に対応している • CloudFormationのテンプレートを記述すれば対応外のものも管理可能 • プラグインを開発することにより、ビルドや更新時の挙動を変更可能 Serverless Frameworkとは 17 -
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で管理。 -
GitHub Flowを採用し、開発環境ではdevelopブランチを自動的に反映、本番環境はmasterブランチ を自動的に反映する様にCodeBuildで設定を行っている。
➡ 検証したい場合は、開発環境などでブランチを指定して ビルドすることにより構成が反映される ServerlessのCD 19 -
• 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 -
バックエンドアーキテクチャ 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 -
• Lambdaの起動時間が許容できない ◦ リクエスト時間がシビアな処理(=CM挿入処理)をLambdaで捌こうと思ったが、AppSync経由で Lambdaからの応答が返ってくる時間が許容できなかった ◦ Provisioned ConcurrencyなLambdaを設定したが、Provisionedでない呼び出しの
タイミングが許容できない ◦ Lambda自体の起動というより、アプリケーションの初期化 (DnyamoDBへのTLS接続など) に 時間を要していた AWS AppSyncを使って直面した課題1 22 ➡ EKS上にCM挿入処理を切り出したアプリケーションを用意し、AppSyncからHTTPを データソー スとして呼び出すようにした -
➡ AppSyncへのリクエストに用いられる Authorization ヘッダーをバイパスして、HTTP側で Cognito のJWTを検証するようにした • HTTPデータソースの呼び出し元がAppSyncであることを検証できない
◦ HTTP側でAppSyncから呼び出した事が保証できないと、セキュリティ上の懸念がある AWS AppSyncを使って直面した課題2 23 Lambda AppSync Operators HTTP Server on EKS Authorization: ... Authorization: ... -
AWS AppSyncを使って直面した課題3 • 障害や問題発生時に、CloudWatchのログのみだと切り分けが難しい ◦ AppSyncへのリクエスト時にCloudWatchに保存されるログは、事象ベースからの検索のハードル が高い ◦ 問い合わせがあった時間から、AWS
AppSyncへのリクエストを検索し、判明したRequestIdや X-Amzn-Trace-Idなどを元に、各種コンポーネントの調査を行う 24 ➡ トレースを行いやすくするツール開発の検討、クライアント側への情報表示の検討 -
Serverlessを使って直面した課題 • Lambdaが増えるごとにビルド時間が増加する ◦ 前述の通り、GraphQLのフィールド毎にバイナリを生成しており、デプロイ時に毎回ビル ドを行っている ➡
シングルバイナリの検討、前回のデプロイと差分がある関数のみビルドを行うようなプラグイン 開発の検討 25 -
まとめ • AWS AppSyncとServerless Frameworkを使うことで、マネージドなGraphQLサーバーを短時間 で構築することができた ◦ 実際、構築と開発にかかった期間は、ロジック部分も含めて3ヶ月ほど •
AWS AppSyncでは、取得系はDynamoDB、更新系はLambdaをデータソースにしている ◦ 一部、Lambdaで許容できない処理はHTTPを呼び出すことで解決 • 構成はGitHub Flowで管理していて、ブランチへのpushをトリガーに自動的に構成が反映され る 26