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

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

生配信管理システムのバックエンド〜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. 2
    山中勇成 a.k.a みゆっき

    株式会社サイバーエージェント 2017年 新卒入社

    株式会社AbemaTV 開発局 コンテンツ配信Div.

    未踏スーパークリエータ

    最近の 買い 欲しい物

    自己紹介
    Panasonic 4Kリモートカメラ 

    AW-UE150


    View full-size slide

  2. 今回の話は、配信システムの大規模刷新プロジェクトであるSUPERBIRDに関連する。

    詳しくは、CA BASE NEXTでの以下の発表を参考。

    前置き
    3
    "新しい未来のテレビ"を目指すABEMA配信システムの再設計
    https://ca-base-next.cyberagent.co.jp/sessions/abema-live-streaming-re-architecture/

    View full-size slide

  3. SUPERBIRDについて
    4
    中央集約(ハブ化) エンコーダーリプレイス
    監視設備強化 新配信管理画面
    各スタジオとデータセンターを専用線で、
    データセンターとクラウドをプライベートピアで接続 品質の高いアプライアンス型の
    専用エンコーダーの導入
    電源や回線が冗長化され、
    レガシーな監視から脱却された
    新しい監視設備を構築
    現場の意見をヒアリングした上
    で、現場が使いやすい管理画面を
    新たに開発

    View full-size slide

  4. SUPERBIRDにより、配信用のオペレーションツールのバックエンドを作り直す必要があった。

    今回話す内容について
    5
    課題

    Streaming
    Server
    Encoder
    Manifest
    Decorator
    この辺りのステータス表示や制御を行うためのツール

    ● コンテンツ配信チームでは、現状2人でABEMAの配信を見ているため、

    できるだけメンテナンスコストを減らしたい

    ● 他の新規案件や改修タスクもあるため、
    できるだけ短時間で構築したい

    ● スキルアップを目的に流行りのツールを使ってみたい


    View full-size slide

  5. 6
    AWS AppSync


    View full-size slide

  6. GraphQLとは



    Facebookにより開発された、WebAPIのためのクエリ言語とそのランタイム

    https://graphql.org/


    ● 少ないリクエストで複数のリソースにアクセス可能

    ● クライアントに必要な最小限のデータだけを取得可能


    ● エンドポイントがリソースやアクションを表していないため、

    キャッシュやモニタリングなど、HTTPのエコシステムを活用しにくい

    7
    Pros

    Cons


    View full-size slide

  7. 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のスキーマとリクエストの流れ

    View full-size slide




  8. 完全マネージド型のGraphQLサーバー

    https://aws.amazon.com/jp/appsync/

    ● DynamoDBやLambdaなどのデータソースと接続し、リクエストを処理可能

    ● 認証やキャッシュ、リアルタイムのサブスクリプション、クライアントSDKと

    連携すればオフラインでの利用なども可能

    ● APIリクエストのボリュームに合わせた GraphQL API 実行エンジンの自動的なスケールアッ
    プとダウンが行われる

    AWS AppSyncとは
    9
    AWS AppSync


    View full-size slide

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

    10
    DynamoDB
    Aurora
    Lambda
    AppSync
    Client
    Schema Resolver
    Cognito
    Data Source
    現時点で対応しているデータソース

    ● DynamoDB

    ● AWS Lambda

    ● Amazon OpenSearch Service

    ● HTTP

    ● Aurora Serverless

    HTTP

    View full-size slide


  10. スキーマのフィールドを解決するための設定

    データソースとマッピングテンプレートを指定する。


    データソースとのリクエストとレスポンスをどう処理するか
    を記述する。

    テンプレートは、ApacheVTLで記述する。

    リクエストテンプレートは、JSON形式で出力することが多
    い。

    11
    GraphQL Request
    Resolver
    Request Mapping Template
    Response Mapping Template
    Data
    Source
    GraphQL Response
    リゾルバーとマッピングテンプレート
    リゾルバー

    マッピングテンプレート 


    View full-size slide

  11. 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にリゾルバーを紐付け

    リゾルバーとマッピングテンプレートの紐付け

    View full-size slide

  12. AWS AppSyncをどの様に使うか
    13
    Lambda
    DynamoDB
    AppSync
    S3
    Operators
    Cognito
    ● AppSyncは、GraphQLのゲートウェイ
    (認証とフィールドの解決) 、DynamoDBへの取得系クエリ
    の処理を行う様に設定

    ● 上記以外の更新系などの処理は、AppSyncからLambdaを呼び出している

    ➡ 更新時には、バリデーションや外部APIの呼び出しなどを行う可能性が高いため、

    処理の柔軟性が高いLambdaを前提として構築した 


    View full-size slide

  13. AWS AppSyncのデバッグ方法
    14
    リクエスト毎にリゾルバーがどう処理され
    たかをログとして出力 

    CloudWatch

    リクエスト毎にリクエストの詳細やデータ
    ソースへのアクセスを分析 

    X-Ray

    ブラウザ上で簡単にGraphQLクエリを実
    行可能(Cognitoの認証も可能) 

    コンソール


    View full-size slide

  14. AWS AppSyncの良い点・悪い点

    ● スケーラブルなマネージドGraphQLサーバが簡単に作れる 

    ● クライアントSDKを使用すれば認証やオフラインキャッシュなども利用可能 


    ● 細かいことをやろうとするとLambdaが必要になる 

    ● テストがしにくい

    ● マッピングテンプレート(Apache VTL)を覚える必要がある 

    ● バリデーションや認可などをマッピングテンプレートに書くことができるが、 

    管理が複雑になる

    15
    Pros

    Cons


    View full-size slide

  15. 社内では、Terraformを用いてAWSリソースを管理することが一般的。

    ただし、それではAppSyncのスキーマ変更やLambdaのコード変更の度にTerraformの反映が必要
    になってしまう。

    AWS AppSyncをどのように構築するか
    16
    CodeBuild Cognito
    DynamoDB
    S3 SQS
    IAM Roles
    Terraformで生成されるリソース 
 Serverlessで生成されるリソース 

    Lambda
    AppSync
    ➡ 基本はTerraform、開発利便性が必要なリソースはServerlessで管理するように

    View full-size slide




  16. サーバレスコンポーネントのために開発された構成管理ツール

    https://www.serverless.com/

    ● AWS Lambdaなどのサーバレスコンポーネントが簡単に構築、管理可能

    ● 様々なProvider(AWS, GCP, Azure, etc...)に対応している

    ● CloudFormationのテンプレートを記述すれば対応外のものも管理可能

    ● プラグインを開発することにより、ビルドや更新時の挙動を変更可能

    Serverless Frameworkとは
    17

    View full-size slide

  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で管理。


    View full-size slide

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







    ➡ 検証したい場合は、開発環境などでブランチを指定して
    ビルドすることにより構成が反映される

    ServerlessのCD
    19

    View full-size slide

  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

    View full-size slide

  20. バックエンドアーキテクチャ
    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

    View full-size slide

  21. ● Lambdaの起動時間が許容できない

    ○ リクエスト時間がシビアな処理(=CM挿入処理)をLambdaで捌こうと思ったが、AppSync経由で
    Lambdaからの応答が返ってくる時間が許容できなかった 

    ○ Provisioned ConcurrencyなLambdaを設定したが、Provisionedでない呼び出しの 

    タイミングが許容できない 

    ○ Lambda自体の起動というより、アプリケーションの初期化 (DnyamoDBへのTLS接続など)
    に

    時間を要していた

    AWS AppSyncを使って直面した課題1
    22
    ➡ EKS上にCM挿入処理を切り出したアプリケーションを用意し、AppSyncからHTTPを
    データソー
    スとして呼び出すようにした


    View full-size slide

  22. ➡ AppSyncへのリクエストに用いられる Authorization ヘッダーをバイパスして、HTTP側で
    Cognito のJWTを検証するようにした

    ● HTTPデータソースの呼び出し元がAppSyncであることを検証できない

    ○ HTTP側でAppSyncから呼び出した事が保証できないと、セキュリティ上の懸念がある 

    AWS AppSyncを使って直面した課題2
    23
    Lambda
    AppSync
    Operators
    HTTP Server
    on EKS
    Authorization: ...
    Authorization: ...

    View full-size slide

  23. AWS AppSyncを使って直面した課題3
    ● 障害や問題発生時に、CloudWatchのログのみだと切り分けが難しい

    ○ AppSyncへのリクエスト時にCloudWatchに保存されるログは、事象ベースからの検索のハードル
    が高い

    ○ 問い合わせがあった時間から、AWS AppSyncへのリクエストを検索し、判明したRequestIdや
    X-Amzn-Trace-Idなどを元に、各種コンポーネントの調査を行う 

    24
    ➡ トレースを行いやすくするツール開発の検討、クライアント側への情報表示の検討

    View full-size slide

  24. Serverlessを使って直面した課題
    ● Lambdaが増えるごとにビルド時間が増加する

    ○ 前述の通り、GraphQLのフィールド毎にバイナリを生成しており、デプロイ時に毎回ビル
    ドを行っている



    ➡ シングルバイナリの検討、前回のデプロイと差分がある関数のみビルドを行うようなプラグイン
    開発の検討

    25

    View full-size slide

  25. まとめ
    ● AWS AppSyncとServerless Frameworkを使うことで、マネージドなGraphQLサーバーを短時間
    で構築することができた

    ○ 実際、構築と開発にかかった期間は、ロジック部分も含めて3ヶ月ほど

    ● AWS AppSyncでは、取得系はDynamoDB、更新系はLambdaをデータソースにしている

    ○ 一部、Lambdaで許容できない処理はHTTPを呼び出すことで解決

    ● 構成はGitHub Flowで管理していて、ブランチへのpushをトリガーに自動的に構成が反映され
    る


    26

    View full-size slide

  26. 27
    この後は...
    このセッションで話したツールのフロントエンドの実装については、

    この後、同トラックで発表予定。

    生配信管理システムのフロントエンド〜配信現場に合わせたアジャイル開発〜
    https://developer.abema.io/2021/sessions/skvMoyXlQM/

    View full-size slide