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

Real-Time applications with GraphQL

joe_re
August 31, 2022

Real-Time applications with GraphQL

GraphQK Tokyo #18 LT資料

GraphQL Subscriptionを利用してどのようにreal-time applicationを構築するか。
GraphQL Subscriptionのスキーマ設計や、運用で気を付けるポイントなど。

joe_re

August 31, 2022
Tweet

More Decks by joe_re

Other Decks in Technology

Transcript

  1. Real-Time applications with GraphQL
    @joe_re
    1/24

    View Slide

  2. Self introduction
    twitter: @joe_re
    github: @joe-re
    GraphQL Tokyo Organizer
    Work for ClassDo
    Live in Singapore
    2/24

    View Slide

  3. Today, I'm going to talk about..
    GraphQL Subscriptionとは何か
    GraphQL Subscription採用におけるメリット
    運用していく中で、自分達が気をつけているポイントを4つのプラクティスとして紹介
    But I'm not going to talk about..
    あくまでGraphQL Subscriptionの運用、設計の話をするので、
    個別の機能要件に関連する話はしません(そこのつらみはたくさんあるけど)
    自分達のアプリケーション特性に基づいた話を運用の経験からお話します。
    全てのアプリケーションにあてはまるという主張ではありません
    3/24

    View Slide

  4. ClassDo
    教育に特化したオンラインミーティングサービス
    オンラインの授業を行う上ではリアルタイムコミュニケーションが超重要
    クライアントから呼び出しているAPIのほぼ全てはGraphQL
    勉強会の用途なら無料で使えるように提供できます。大人数向けのカンファレンスには
    向いていないけど、少人数のセッションを運営している方などぜひ!
    We're hiring!(特にGraphQLでリアルタイムなインタラクションを実装してみたい方!)
    4/24

    View Slide

  5. DEMO
    5/24

    View Slide

  6. What is GraphQL Subscription
    QueryやMutationと同じくGraphQLのオペレーションの1つ
    Schemaの変更をリアルタイムにサーバより受け取るためにコネクションを作る
    (WebSocketが主流)
    QueryやMutationと違い、長くライフサイクルを持つオペレーションになる
    6/24

    View Slide

  7. Simple example
    ある記事に対してコメントの追加を検知する
    subscription AddedComment {

    addedComment {

    id

    text

    author

    article

    }

    }

    7/24

    View Slide

  8. Why GraphQL Subscription is good with us
    当初はリアルタイムな同期を想定していないエンティティも、
    機能開発によって必要になることが多い
    新しく追加される同期処理に対してインタラクションの設計の手間がかからない
    Query, Mutationと同じスキーマを共有しているので、GraphQLスキーマ上に存在する
    全てのエンティティがsubscribableだと考えられるようになる
    8/24

    View Slide

  9. The actual case for everything can be subscribable
    9/24

    View Slide

  10. Our architecture of Subscription
    10/24

    View Slide

  11. Practice 1
    Subscriptionでは重い処理は書かない
    11/24

    View Slide

  12. Subscriptionでは重い処理は書かない
    Subscriptionへの通知は、Mutationが実行されたあとに即座に通知されることが超重要
    この原則を守ることで、ある程度細かいインタラクションを実装せずともまともな
    ユーザ体験を届けることができる(もちろん機能や程度にはよる)
    重い計算処理が必要ならMutationに寄せて、Subscriptionは値を受け取るだけにする
    Subscription: { //
    こんな実装はなるべく避ける

    post: {

    subscribe(parent, args, { pubsub }) {

    return pubsub.asyncIterator('post');

    },

    async resolve(parent, args, context) {

    // It's too heavy query

    const posts = await db.getTooHeabyObject({

    args: args.foo

    })

    return posts

    }

    },

    }

    12/24

    View Slide

  13. Practice 2
    Clientでrefetchingやpollingをなるべくしない
    13/24

    View Slide

  14. Clientでrefetchingやpollingをなるべくしない 1
    Mutationの結果、直接変更したエンティティが別のエンティティに影響を与えるケース
    ってありますよね
    簡単な例だとこういうやつ
    //
    このMutation
    の結果

    mutation postArticle(input: {

    title: String!

    content: String!

    //..

    }) {

    //..

    }

    type User {

    id: ID!

    numberOfPostedArticles: Int! //
    ここが変わる

    //...

    }
    14/24

    View Slide

  15. Clientでrefetchingやpollingをなるべくしない 2
    解決策として一般的に思いつくのは
    1. Mutationの後にrefetchingを叩くことで強制的に同期する
    2. Mutaionの結果にUpdateが想定されるオブジェクトを含める
    3. Subscriptionに変更の検知の全てを委ねる
    15/24

    View Slide

  16. Clientでrefetchingやpollingをなるべくしない 3
    refetchingは重くなる可能性が高い
    上記のように簡単な例ならMutationの結果に変更が想定されるオブジェクトを含めれば
    変更をリアルタイムに適用できる
    mutation postArticle(input: {

    title: String!

    content: String!

    //..

    }) {

    //..

    author { id, numberOfPostedArticles }

    }

    でもこのエンティティの関係がもっと遠いとMutationの返り値で取得するのは難しいか
    もしれない
    そもそも変更検知は自分ではなく、リモートのユーザに必要かもしれない 16/24

    View Slide

  17. Clientでrefetchingやpollingをなるべくしない 4
    前提として、更新の影響を受けるのは別のエンティティのプロパティなので、
    demand-driven APIであるGraphQLにおいては更新が必要かどうかは
    クライアントの関心ごとになる
    サーバとしては更新のあったエンティティに対して変更の通知さえすれば、
    その後それを採用するかどうかはクライアントの責務と言える
    同期処理を1つ1つのインタラクションについて個別に考えるより、
    更新の発生したエンティティにはとりあえず変更イベントを発火しておいた方が
    実装としても楽
    17/24

    View Slide

  18. Practice 3
    Query, MutationとSubscriptionの両方で再利用可能なSchema設計をする
    18/24

    View Slide

  19. Query, MutationとSubscriptionの両方で再利用可能なSchema設計をする 1
    現在見ているタブの同期処理をコマンドベースに考えると..
    19/24

    View Slide

  20. Query, MutationとSubscriptionの両方で再利用可能なSchema設計をする 2
    Subscriptionにおいてはどのエンティティの変更(CRUD)なのかを考える
    20/24

    View Slide

  21. Practice 4
    Subscriptionが起動するインスタンスはHTTPサーバと分離する
    21/24

    View Slide

  22. Subscriptionが起動するインスタンスはHTTPサーバと分離する
    HTTPサーバとSubscriptionサーバとでは消費するコンピュータリソースが違う
    Subscriptionはコネクションを維持しているので、なるべくスケーリングの頻度は落と
    して瞬断などが発生する機会を減らしたい
    もしインスタンスを分けていないと、HTTPサーバの負荷に伴ってスケーリングの変更が
    された場合にSubscriptionにはその必要がないのに影響を受けてしまう可能性がある
    22/24

    View Slide

  23. まとめ
    GraphQLのサブスクリプションはGraphQLのスキーマの世界に
    リアルタイム性を導入できる
    気をつけるべき点を押さえておけば運用も難しくはない
    健全なReal-Time Application Lifeを!
    23/24

    View Slide

  24. Thank you!
    24/24

    View Slide