Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GoとGraphQLを使用したサービス開発 / Develop GraphQL service...
Search
Yuki Suwa
November 13, 2021
Programming
0
800
GoとGraphQLを使用したサービス開発 / Develop GraphQL service with Go
Go Conference 2021 Autumn
Yuki Suwa
November 13, 2021
Tweet
Share
Other Decks in Programming
See All in Programming
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
7
2.3k
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.3k
実はマルチモーダルだった。ブラウザの組み込みAI🧠でWebの未来を感じてみよう #jsfes #gemini
n0bisuke2
3
1.3k
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
1.4k
AIエージェントの設計で注意するべきポイント6選
har1101
5
1.3k
【CA.ai #3】ワークフローから見直すAIエージェント — 必要な場面と“選ばない”判断
satoaoaka
0
270
SwiftUIで本格音ゲー実装してみた
hypebeans
0
440
Navigation 3: 적응형 UI를 위한 앱 탐색
fornewid
1
370
AIコーディングエージェント(skywork)
kondai24
0
180
実は歴史的なアップデートだと思う AWS Interconnect - multicloud
maroon1st
0
230
TestingOsaka6_Ozono
o3
0
170
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
2
220
Featured
See All Featured
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
72
How GitHub (no longer) Works
holman
316
140k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
1
200
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
18
ラッコキーワード サービス紹介資料
rakko
0
1.7M
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
34k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
0
88
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.4k
The Pragmatic Product Professional
lauravandoore
37
7.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Amusing Abliteration
ianozsvald
0
63
Transcript
GoとGraphQLを使用したサービス開発 Yuki Suwa (@flum_) Go Conference 2021 Autumn
Agenda 1. 自己紹介 2. 新規事業何が大変か 3. GoやGraphQLの採用理由 4. 実装の課題 5.
工夫していること 6. まとめ
自己紹介 • 諏訪 侑希 • Github: flum1025 • Twitter: @flum_
• Retty株式会社 ◦ RettyOrder開発リーダー ◦ 普段はFrontend, Backendの 設計から実装までやってます • Go歴: 3年
食を通じて 世界中の人々を Happyに。 世界に誇る日本の文化であり、世界中の人々の 暮らしの中心でもある、「食」という分野で、お店を探 す人とお店の人の双方がHappyに なれる、そんな世界を実現したい。その為に、 お店をオススメするというポジティブな感情で 人をつなぐ事がRettyの目標です。 コーポレートビジョン
どういうサービスなのか
どういうサービスなのか Retty Order ユーザー 店員 ①注文 ④提供 ②通知 ③調理
新規事業何が大変か
新規事業何が大変か • 刻々と変化する状況 • 限られたリソースと時間 • ヒアリングだけだと表に出てこない細かい課題や実際のオペレーション
新規事業何が大変か • 刻々と変化する状況 ◦ => 方向転換に耐えうる設計にしたい • 限られたリソースと時間 ◦ =>
複雑な設計にすると運用コストが大きくなる可能性が高い • ヒアリングだけだと表に出てこない細かい課題や実際のオペレーション ◦ => 大きく作ると無駄になる可能性が高い
新規事業としての要件 • スピードが重要なのでなるべくシンプルに早く実装したい ◦ かといって機能開発に振り切ると負債の解消ができず後々死ぬ • 将来的に開発体制をスケールできる設計を目指したい • 金銭を扱うサービスになるのでなるべく安全に実装したい •
お店の根幹を担うサービスになるのでEntityの種類が増えそう
実装方針
実装方針 • スピードが重要なのでなるべくシンプルに早く実装したい ◦ => GraphQLを採用してスキーマ駆動開発 ▪ 実装前にスキーマさえ決めればフロントエンド、バックエンド、アプリを平行して実 装できる
実装方針 • 将来的に開発体制をスケールできる設計を目指したい ◦ => Clean Architectureを採用しドメイン駆動設計 ▪ ドメインモデリングしていれば、モノリスで作ったとしてもスケールしたタイミング で切り出しやすい
実装方針 • 金銭を扱うサービスになるのでなるべく安全に実装したい ◦ => Goを採用し静的に型付けする ◦ => Clean Architectureならレイヤーごとにテストしやすい
実装方針 • お店の根幹を担うサービスになるのでEntityの種類が増えそう ◦ => GraphQLなら欲しいデータをクライアントで定義できる ▪ Resolverさえ実装すればusecaseごとにエンドポイントを用意しなくてよい
RettyにおけるGoとGraphQL
RettyにおけるGoとGraphQL • Rettyでは一部のマイクロサービスとしてGoとGraphQLが採用 されている • 社内での運用実績、知見が少しだが溜まっていた https://engineer.retty.me/entry/2021/06/04/110000
実装上の課題
実装上の課題 Retty Order ユーザー 店員 ①注文 ④提供 ②通知
③調理
通知の課題 • リアルタイム性が求められる • 注文ごとにイベントが発生するため、メッセージ量が多い • 元々はポーリングで実装していた ◦ ポーリングの間隔によってはリアルタイムとは言えない ▪
間隔下げれば下げるほど負荷が高い ◦ データ数が多く全データ取得するには負荷が高い ▪ 一部だけポーリングで取得するような実装もつくれるには作れるが、、
そこでGraphQL Subscription • GraphQL上のPub/Subの仕組み • Mutation等で発生したイベントなどをリアルタイムに購読できる • GraphQL自体はトランスポート層に依存しないので実装は好きな物を選べる ◦ 以下の実装はgqlgenに標準で備わっているため簡単に利用できる
▪ WebSocket ▪ Long Polling(一回のイベント通知のみ) ◦ Transportの実装をカスタムできるので、やろうと思えばServer-Send Event(SSE) やHTTP Streamingでも実装できそう
GraphQL Subscriptionを実装するには • 基本的に世のWebアプリケーションはスケールが前提 • アプリケーションサーバー間でもイベントを共有できる仕組みが必要 ◦ どのサーバーに繋がったとしても同じイベントを購読したい • アプリケーションサーバー間のPub/SubとしてRedisを置くことでどの
サーバーに繋がったとしても同じイベントが購読できる • Subscriptionでは並行処理を多用するのでGoと相性がいい
運用中に起きたこと
Redisのバッファーが詰まる • ある日、注文画面が更新されないという報告が来た • 本番環境にアクセスしたところ、 WebSocketのコネク ションは繋がっており、Authentication, Initializationは 正常にできていた •
しかし、イベントを発生させてみてもメッセージが流れて くる様子がない • Redisのメトリクスをみても負荷が特段高いわけではな く、コネクション数等もかなり余裕があった conneciton_initとSubscriptionクエリが発行されている様子
Redisのバッファーが詰まる
Redisのバッファーが詰まる • GraphQLサーバーのログをみたところ、go-redisの channel is fullというログが発生していた • リソース節約のため同イベントの購読は Redisの Subscribeを使いまわす実装になっていた
• 調査したところネットワークが遅いクライアントがいた場 合、メッセージの送信に時間がかかり bufferを食い潰すこ とがわかった timerを利用してメッセージの送信に時間が かかり過ぎる場合は購読を切る仕組みを作 成
パフォーマンス監視
パフォーマンス監視 • 本番で運用するにはサービスの監視だけではなく、 アプリケーション内部を監視しボトルネック を特定させる必要がある • gqlgenを採用する場合パフォーマンス監視の仕組みを自前で作る必要がある ◦ Apollo Tracingには一応対応している
▪ が、レスポンス(or ログ)を監視して送る仕組みは自分でつくらないといけない ▪ GraphQL以外の部分のTraceとの紐付けができない ◦ 過去にはOpenCensus, OpenTracing等に対応していたっぽいが、メンテしておらず最新のバー ジョンでは利用できない ◦ gqlgenにはプラグインの仕組みがある ▪ 自前でプラグインを作って APMに送る仕組みを作成
gqlgenのパフォーマンス監視 ResponseIntereceptor FieldInterceptor • InterceptResponseを使用すると各 オペレーションの実行時に呼び出せ る • InterceptFieldで各Fieldの実行時に 呼び出せる
• Datadog等を使う場合はContextを 利用してOperationとFieldに親子関 係を持たせられる [Point] InterceptFieldは構造体のFieldからデータを取得する際にも 実行されてしまうので、 Resolver関数が定義されてるものに絞る 構造体のFIeldから取得する場合は親の Field解決時にデータ取得済 みなのでここでトレースする必要はない
gqlgenのパフォーマンス監視
開発で工夫していること
レプリカラグを意識した開発 • Amazon Aurora MySQLを使用している • Aurora MySQLは一般のMySQLよりは低遅延だが、遅延はある ◦ 公式では100ms未満と記載されている
• レプリカラグを意識した開発を強制している ◦ Readerインスタンスに `MASTER_DELAY=1` つけるだけ https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/A urora.Replication.html
まとめ
こういう実装方針でした • スピードが重要なのでなるべくシンプルに早く実装したい ◦ => GraphQLで解決 • 将来的に開発体制をスケールできる設計を目指したい ◦ =>
Clean Architectureで解決 • 金銭を扱うサービスになるのでなるべく安全に実装したい ◦ => GoとClean Architectureで解決 • お店の根幹を担うサービスになるのでEntityの種類が増えそう ◦ => GraphQLで解決
採用してどうだったか • Go ◦ 良くも悪くもシンプルなので、ロジックに対するレビューに集中できる ◦ コードが冗長になるのはちょっと辛い • CleanArchitecture ◦
ドメインモデリングのために議論が盛んに ▪ レビュー前に議論すると大きな手戻りが減らせるし今後の拡張もしやすくなる ▪ ドメインについてちゃんと考える必要があるのでスコープも小さくなる ◦ テストがしやすいのでテストコードが増えて行きやすい ▪ カバレッジが全てではないが、開発時の安心感は絶大 ▪ テストがあると思い切ったリファクタがしやすいので開発効率を保てる • GraphQL ◦ 新しいデータに依存しない部分はフロントで完結できるので、フロントの開発スピードは早 い カバレッジは90%ある