$30 off During Our Annual Pro Sale. View details »

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

  2. Self introduction twitter: @joe_re github: @joe-re GraphQL Tokyo Organizer Work

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

  5. DEMO 5/24

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

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

    author article } } 7/24
  8. Why GraphQL Subscription is good with us 当初はリアルタイムな同期を想定していないエンティティも、 機能開発によって必要になることが多い 新しく追加される同期処理に対してインタラクションの設計の手間がかからない

    Query, Mutationと同じスキーマを共有しているので、GraphQLスキーマ上に存在する 全てのエンティティがsubscribableだと考えられるようになる 8/24
  9. The actual case for everything can be subscribable 9/24

  10. Our architecture of Subscription 10/24

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

  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
  13. Practice 2 Clientでrefetchingやpollingをなるべくしない 13/24

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

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

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

    content: String! //.. }) { //.. author { id, numberOfPostedArticles } } でもこのエンティティの関係がもっと遠いとMutationの返り値で取得するのは難しいか もしれない そもそも変更検知は自分ではなく、リモートのユーザに必要かもしれない 16/24
  17. Clientでrefetchingやpollingをなるべくしない 4 前提として、更新の影響を受けるのは別のエンティティのプロパティなので、 demand-driven APIであるGraphQLにおいては更新が必要かどうかは クライアントの関心ごとになる サーバとしては更新のあったエンティティに対して変更の通知さえすれば、 その後それを採用するかどうかはクライアントの責務と言える 同期処理を1つ1つのインタラクションについて個別に考えるより、 更新の発生したエンティティにはとりあえず変更イベントを発火しておいた方が

    実装としても楽 17/24
  18. Practice 3 Query, MutationとSubscriptionの両方で再利用可能なSchema設計をする 18/24

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

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

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

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

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

  24. Thank you! 24/24