Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQLサーバを作る苦しみと解決手法
Search
mackee
July 21, 2020
Technology
16
9.4k
GraphQLサーバを作る苦しみと解決手法
吉祥寺.pm23
https://kichijojipm.connpass.com/event/182287/
mackee
July 21, 2020
Tweet
Share
More Decks by mackee
See All by mackee
ワンバイナリWebサービスのススメ
mackee
10
7.8k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
100
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
640
perl for shell, awk and sed programmers
mackee
2
2.2k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
610
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
500
マイクロサービス化を利用した Goへの移行事例
mackee
0
630
PerlでつくるフルスクラッチWebAuthn/パスキー認証 / Demonstration of full-scratch WebAuthn/Passkey Authentication written in Perl
mackee
3
4.5k
SRE定例やその辺の取り組みをアプリケーションエンジニア目線で語る / "Observe" about SRE Meeting by Application Engineer
mackee
0
1.9k
Other Decks in Technology
See All in Technology
ひとり情シスなCTOがLLMと始めるオペレーション最適化 / CTO's LLM-Powered Ops
yamitzky
0
370
ローカルLLMでファインチューニング
knishioka
0
120
Observability infrastructure behind the trillion-messages scale Kafka platform
lycorptech_jp
PRO
0
130
AIの最新技術&テーマをつまんで紹介&フリートークするシリーズ #1 量子機械学習の入門
tkhresk
0
120
AIにどこまで任せる?実務で使える(かもしれない)AIエージェント設計の考え方
har1101
3
1.2k
In Praise of "Normal" Engineers (LDX3)
charity
2
1.2k
2年でここまで成長!AWSで育てたAI Slack botの軌跡
iwamot
PRO
2
140
Create a Rails8 responsive app with Gemini and RubyLLM
palladius
0
140
AWS Summit Japan 2025 Community Stage - App workflow automation by AWS Step Functions
matsuihidetoshi
1
140
讓測試不再 BB! 從 BDD 到 CI/CD, 不靠人力也能 MVP
line_developers_tw
PRO
0
1.1k
ハノーバーメッセ2025座談会.pdf
iotcomjpadmin
0
140
Uniadex__公開版_20250617-AIxIoTビジネス共創ラボ_ツナガルチカラ_.pdf
iotcomjpadmin
0
140
Featured
See All Featured
Building an army of robots
kneath
306
45k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
It's Worth the Effort
3n
184
28k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Adopting Sorbet at Scale
ufuk
77
9.4k
Product Roadmaps are Hard
iamctodd
PRO
53
11k
The World Runs on Bad Software
bkeepers
PRO
68
11k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.3k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Unsuck your backbone
ammeep
671
58k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
Transcript
GraphQLαʔόΛ࡞Δۤ͠Έ ͱղܾख๏ @mackee_w a.k.a macopy 2020-07-21 ٢ࣉ.pm23
͢͜ͱ • ͱͱGraphQLʹջٙతͩͬͨਓ͕ • GraphQL͕͢ͰʹΘΕ͍ͯΔϓϩδΣΫτͰͪΐͬͱۤ͠Έ • ࡞Γͧ͢ʂͱͳͬͨͱ͖ʹ·ͨGraphQLΛ͏ཧ༝
macopy *ʮ ߏମҠ͠ସ͑ۀʯ * WebΞϓϦέʔγϣϯΤϯδχΞ * ୲αʔόαΠυ(Perl/Go) * Ϛελσʔλཧ͕ಘҙͰ͕͢࠷ ۙͦ͏͍͏ࣄ͕͋Γ·ͤΜ
࠷ۙͷ͓ࣄ
ࠓͷओ GraphQL
͔ͯ͠͠٢ ࣉpmʹGraphQL ͷ͕དྷ͍ͯ Δʁʁʁ
GraphQL͓͞Β͍ • Web͚ΫΤϦݴޠ • ಉׂ͡Λ͢Δͷ: OpenAPI, gRPC, JSON-RPC… • GitHubͳͲͷWeb
APIͰ࠾༻ྫ͋Γ • `/graphql`Έ͍ͨͳ୯ҰͷΤϯυϙΠϯτʹΫΤϦΛ͛Δ • ϨεϙϯεJSON͕Α͘ΘΕΔ(͕ɺผʹԿͰྑ͍ͣ)
GraphQLΛ͏ͱ͖ͷྲྀΕ εΩʔϚ ΫΤϦ ม Ϩεϙϯε POST /graphql
GraphQLɺԿ͕͏Ε͍͠ͷʁ • ܕ͕͋ͬͯૉΒ͍͠ • ܕ໊ʹ`!`͕ͭ͘ͱnot nullable • ඞཁͳfieldͷߜΓࠐΈɺҰॹʹऔΓ͍ͨϦιʔεͷҰׅऔಘͰ͖Δ • ࣹӨbatch
requestΈ͍ͨͳΈΛ࡞Γࠐ·ͣʹࡁΉ • पลπʔϧ/ϥΠϒϥϦ͕͍ͬͺ͍͋ͬͯૉΒ͍͠ • GraphiQL, apollo-client/apollo-server ͳͲͳͲ
͜ͷ”͏Ε͍͠” ୭ͷࢹ͔ʁ
αʔό(Perl)୲ͷࢲࢹͰݟΔͱ
GraphQLɺԿ͕͏Ε͍͠ͷʁ • ܕ͕͋ͬͯૉΒ͍͠ • ܕ໊ʹ`!`͕ͭ͘ͱnot nullable • ඞཁͳfieldͷߜΓࠐΈɺҰॹʹऔΓ͍ͨϦιʔεͷҰׅऔಘͰ͖Δ • ࣹӨbatch
requestΈ͍ͨͳΈΛ࡞Γࠐ·ͣʹࡁΉ • पลπʔϧ/ϥΠϒϥϦ͕͍ͬͺ͍͋ͬͯૉΒ͍͠ • GraphiQL, apollo-client/apollo-server ͳͲͳͲ ←ͤͳͰαʔόɺPerlͶΜ… ɹundefେܴͶΜ… ↑͑ɺͭ·Γൃߦ͞ΕΔSQL͕ݻఆͰ͖ͳ͍ʁʁ ɹࠔΔͷͰʁʁʁ ↑ͦΕPerlʹ͋Δͷʁʁʁʁʁ
GraphQLΛຊ֨తʹ͏લ·Ͱͷҹ(1) • ΫϥΠΞϯτଆͷૢ࡞ͰσʔλͷऔΓग़͠ํ͕ಈతʹมΘΓ͏Δͷड ͚ೖΕ͕͍ͨ • ύϑΥʔϚϯενϡʔχϯά͕͔ͳΓ͍͠ • RESTful APIʹൺͯGraphQLͰN+1ͷղܾ͕͍͕͜͜͠ΩϞ ͩͱࢥΘΕΔ
• RESTful APIͰฦ͢σʔλͷܗ͕ҰఆͩͱܾΊଧͪνϡʔχϯάͰ͖ Δ GraphQLͦΕ͕ग़དྷͳ͍
GraphQLΛຊ֨తʹ͏લ·Ͱͷҹ(2) • GitHub API v4(GraphQL)͕ग़ͨͱ͖ʹΘʔ͍ͱ৮ͬͯΈͨͱ͖ͷײ • GraphQLݴޠΛ֮͑Δͷ͕ղ(ʹݟ͑ͨ) • ୯ͳΔJSONͷੜͰͳ͍ಠࣗDSL •
ͪΐͬͱෳࡶͰωετ͕ਂͯ͘ྔ͕ଟ͍ΫΤϦΛൃߦ͢Δͱ500͕ฦ͖ͬͯͨ • ʮGitHubͰ͢Β͜͏ͳΔΜ͔ͩΒզʑʹ…ʯ • ͨͿΜࠓComplexityΛܭࢉͯ͠200Ͱฦͤͳ͍Αͱݴͬͯ͘ΔͷͰͳ͍͔
͕ٕज़બ͢ΔͳΒબͳ͍ͩΖ͏…
ԑ͕ͳ͍ͱࢥ͍͕ͬͯͨɺ͔͠͠…
ࠓ಄ʹҟಈͨ͠ ςʔϚʮࠓͷલͷ׆ಈΛৼΓฦΔʯ
ҟಈޙͷձ • ʮͳΜ͔͜ͷϖʔδදࣔ͞ΕΔ·Ͱॏ͍͠ɺαʔό͘͢͝CPU৯͏ ΜͰ͢ΑͶʯ • ʮͲΕͲΕݟͯΈΔ͔…͋͋׳Ε͠ΜͩPerlͩ…ʯ •ʮͬɺGraphQLͩ…ʯ
ॏ͍ϖʔδΛνϡʔχϯά͢Δ • ͜ͷ࣌ͰԿ͕ݪҼ͔Θ͔Βͳ͍ • GraphQLͰͳ͘ɺΞϓϦέʔγϣϯϩδοΫͷํʹݪҼ͕͋Δ͔ • WebΞϓϦαʔόͷCPUΛ৯͏࣌ͰDBͰͳ͍ • …͔͜͠͠ͷࡐͷൃදͰ͜͜ʹॻ࣌͘ͰΦν͕ݟ͍͑ͯΔ •
ͳʹͱ͋ΕͦͷϖʔδͰୟ͔Ε͍ͯΔAPIΛൈ͖ग़ͯ͠ϑϨʔϜάϥ ϑΛग़ͧ͢
Devel::NYTProfͷ݁Ռ • ԣ͕࣠࣌ؒͰॎ͕ίʔϧελοΫ • ͖Ε͍ͳϏϧ͕ݐͬͨ • ΞϓϦέʔγϣϯϩδοΫ ؙ͍ͷ෦ • Ϗϧ͕ݐͬͯΔͷResolverͱݺ
ΕΔfieldΛղܾ͢ΔϝιουΛ ࠶ؼతʹ୳͍ͯ͠Δ෦
PerlͷGraphQL.pm • ࠷ઌͷϞμϯPerl • Function::Parameters • Return::Type • ܕ͕ΨνΨνʹॻ͔Ε͍ͯΔ •
͔͠͠Perlಈతܕ͚ݴޠͳͷͰಈతʹ ܕνΣοΫ͠·͢ • ↑͕͜͜ϘτϧωοΫʹͳΔ • ܕνΣοΫΛແޮԽ͢ΔΑ͏ʹ Function::ParametersΛ͍͡ΔͱΫΤϦ୯Ґ Ͱݟͯ3ഒߴԽ͞Εͨ
GraphQL APIͷߴԽͷҊ • GraphQL.pm͓ΑͼFunction::ParametersΛ͍ͬͯ͡Pull RequestΛग़͢ • ܕνΣοΫແޮԽຊମΛ͍͡Δ͔͠ແ͍ • ͕ɺ͜ͷPull Request͕Authorʹཧղ͞ΕΔࣗ৴͕ͳ͍…͋ͱͬ͞͞ͱղܾ͍ͨ͠
• Ωϟογϡ͢Δ • GraphQLͰΘΕΔresolverϦιʔε୯ҐͷΩϟογϡͰແҙຯ • GraphQLΛύʔεͨ࣌͠Ͱෛ͚͕֬ఆ͍ͯ͠Δ • GraphQLΛGraphQL.pmͰύʔε͢ΔલʹϨεϙϯεΩϟογϡΛฦ͢ => ࠾༻
GraphQLΩϟογϡ͕ࠔͱ͍͏ᷚ • ΤϯυϙΠϯτ1Օॴ, ΫΤϦbodyʹ٧ΊΒΕ͍ͯΔͷͰ… • query stringʹΫΤϦΛೖΕͯϨεϙϯεΩϟογϡ͢Δख๏ͳͲ ͋ΔΒ͍͠ • nginxͰͳ͘Perlʹདྷ͔ͯΒΩϟογϡ͢Δ͜ͱʹ͠ɺBodyಡΉ
• ͔͠͠BodyΛGraphQLͱͯ͠ಡΉͱෛ͚ͳͷͰGraphQLͱͯ͠ಡ ·ͳ͍
ΫΤϦΛϋογϡԽͨ͠ͷΛredisͰ ϨεϙϯεΩϟογϡ ※ηογϣϯͳͲߟྀ͢Δͱ͔,$variablesnormalize͢ΔͳͲ͏গ͕͠ඞཁ
CPUͷεύΠΫ͕؇͞Εͯ ΊͰͨ͠ΊͰͨ͠
ୈೋষ ͜ͷମݧΛͨ͠ਓ͕ؒ શ෦࡞Γ͠ΛΔͱ͖ʹ ·ͨGraphQLΛબΔ͔
શ෦࡞Γ͠ͷܦҢ • ͜ͷGraphQLΛ͍ͬͯΔ෦ɺͦΕൈ͖ʹ͔ͯ͠ͳΓࠐΈೖͬ ͨϩδοΫ͕ೖ͍ͬͯΔ • νʔϜͰཧղͰ͖͍ͯΔਓ͕গͳ͍ • ͔͠͠αʔϏεͷ֩ͷ෦ͳͷͰ༷มߋػೳՃΛόϯόϯೖΕ ͍ͨ •
͔ͳΓͰ͔͍ػೳՃΛ͍ͨ͠ => ࡞Γ͔͢…
࡞Γ͍ͭ͢ͰʹGraphQLΛ˓˓͍ͨ͠ • ݱঢ়ͷΈෳࡶͳGraphQLΫΤϦΛॻ͘ͱWebαʔό͕ॏ͘ͳΔ ಛੑ • ΩϟογϡͰ͖ΔͷඇϩάΠϯϢʔβͰϦΞϧλΠϜੑ͕ແ͍༰ͩ ͚Ͱݶք͕͋Δ • ͦͦGraphQLΛ˓˓ͯ͠ղܾ͍ͨ͠ •
◦◦ʹʮΊΔʯͱ͔ʮҡ࣋ͨ͠··ΈΛม͑Δʯͱ͔ͦͷ Μ͕ೖΓ·͢
࡞Γ͢ଞͷཁҼ • ύϑΥʔϚϯεཁ͕݅ଞͷ෦ͱҧ͏ • िͳͲʹਓ͕ϫοͱདྷͨΒΘΕΔ͕ීஈશ͘ΘΕͳ͍ • ࠷ۙਓ͕૿͑ͯDBෛՙؾʹͳΓ࢝Ίͨ
GraphQLے͕ѱ͍ͷ͔ʁ • ͜ͷ͚ͩฉ͘ͱʮͬۙدΒΜͱ͜ʯͬͯࢥ͏ਓ͍Δ͔ • Γ͚ͯߟ͑Δ • ݱঢ়ͷΈΑΓ͍͍ղ๏͕͋Δͷ͔ • ͦΕͱ •
GraphQLࣗମ͕ۤ࿑ʹରͯ͠Ϧλʔϯ͕߹ͬͯͳ͍ͷ͔
WebϑϩϯτΤϯυଆͷਓʹҙݟΛฉ͍ͯΈΔ • ʮ͢Ͱʹ։ൃ͕͜ͳΕ͖͍ͯͯΔʯʮπʔϧνΣΠϯͷϊϋཷ·ͬͯ ͍Δʯ • ͦͦϑϩϯτΤϯυଆTypeScriptΛશ໘తʹ࠾༻͍ͯͯ͠GraphQLͱ ૬ੑ͕ྑ͍ • ੈؒʹࣄྫ͕ᷓΕ͍ͯΔΈ߹Θͤ •
ҊͷgRPC(Web͔Gateway)ͩͱΈ͔Βߏங͢Δ͜ͱʹͳΔ • ʮWebϑϩϯτΤϯυଆͷਓ͕GraphQLҎ֎Λ࠾༻͢Δಈػͳͦ͞͏ʯ
಄ΛϦηοτͯ͠GraphQLΛ͏·͘αʔόͰѻ ͏͜ͱΛߟ͑Δ • Perlͷ··͍͘ͷͦ͠͏ • ѻ͏ʹGraphQL.pm΄΅ҰͳͷͰ • खલʹapollo-serverཱͯͯREST APIͱ૬ޓม͢ΔͷͳΒ… •
Goࣄྫ͕গ͚ͩ͋͠ΔͬΆ͍ ϥΠϒϥϦ͍͔ͭ͋͘Δ • TypeScriptͰ͑Δ੩తܕͷϝϦοτGoͳΒड͚ΒΕΔ
͔͠͠GraphQLͷαʔόΛ࡞Δ͜ͱࣗମͷ ͋Δ • DBʹରͯ͠N+1ΫΤϦ • ωετͨ͠ΓෳࡶͳΫΤϦΛೖΕΒΕͨͱ͖ʹDoSΈ͍ͨʹͳΒͳ͍ ͔ • Ωϟογϡ͍͠ •
etc…etc…
͔͠͠GraphQLͷαʔόΛ࡞Δ͜ͱࣗମͷ ͋Δ • DBʹରͯ͠N+1ΫΤϦ • ωετͨ͠ΓෳࡶͳΫΤϦΛೖΕΒΕͨͱ͖ʹDoSΈ͍ͨʹͳΒͳ͍ ͔ • Ωϟογϡ͍͠ •
etc…etc… Ұճۤ࿑ͨ͠͠ ͳΜͱ͔ͳΔ͔ͳͱࢥͬͨ
ҰͭҰͭղܾ͍ͯ͘͠աఔ
GraphQLύʔαʔ/Resolver => gqlgen • εΩʔϚ͔ΒResolverΛࣗಈੜ͢ΔϥΠϒϥϦ
N+1ͷղ๏ => vektah/dataloaden • ӈͷ͍߹Θͤϓʔϧ ͷ෦Λࣗಈੜ͢Δ ϥΠϒϥϦ • Ұఆ࣌ؒͷಉ͡ςʔ ϒϧʹର͢ΔΫΤϦΛ
·ͱΊΒΕΔ
ෳࡶͳΫΤϦʹର͢Δख๏ • Query Complexity • ΫΤϦͷResolverΛ࣮ߦ͢Δલʹॏ͍ΫΤϦ͡Όͳ͍͔ௐΔ • ۩ମతʹϖʔδϯάΛڧ੍͢ΔͳͲͯ͠औಘ͢Δ࠷େ݅ΛΫΤϦ Ͱ֬ఆͤ͞Δ =>
ᮢΛ͏͚ͯ͘ • ϖʔδϯάܗࣜ => Relay Server Specification • ҾϨεϙϯεܗࣜʹσϑΝΫτελϯμʔυ͕͋ΔͷͰ͜ΕΛ͏
͜ͷลͷΈͰٙղফͯ͠ ࠓຊ൪ೖʹ͚ͯಈ͍͍ͯΔͱ͜Ζ
͜͜ͰҰ۟ ྑༀ ɹɹޱʹۤ͠ ɹɹɹɹGraphQL
·ͱΊ • GraphQLʹର͢Δ߅ײԿͩͬͨͷ͔͕গ͠Θ͔ͬͨ • ͨͿΜࠓ·Ͱͷαʔόͷ࡞ΓํΛ੍ݶ͢Δ༷ • ৽͍͠ύϥμΠϜͱ͢ΔͱɺڵຯΛ࣋ͬͯऔΓΊͨ • ৽͍ٕ͠ज़Λ࠾༻͢Δ͜ͱɺͦͷٕज़ͷະདྷʹϕοτ͢Δ͜ͱ •
ϕοτ͢Δͱ͍͏͜ͱɺ͍͟ͱͳΕOSSʹPull RequestΛग़ͨ͠Γɺϓ ϩδΣΫτʹΊΔΑ͏ͳओମతͳಈ͖͕ٻΊΒΕΔ • ͜͏ͬͯࣄྫΛग़͢ͷߩݙ͔͠Εͳ͍ͱࢥͬͯͬͯ·͢
͓·͚
ͭΒ͍ͭ: root queryͷnode • Relay Server Specificationʹྫࣔ͞Εͯ ͍Δͭ • ผʹඞਢͰͳ͍͕ɺΫϥΠΞϯτଆ
͋Δͱศར • ΫϥΠΞϯταΠυͷΩϟογϡߋ৽ͷ ͨΊʹNodeͩͬͨΒͳΜͰฦͤΔͭ • αʔόαΠυ`ID`͚ͩͰͲͷܕ͔Λఆ ͠ͳ͚ΕͳΒͳ͍
GitHubͷղ๏ idʹܕใຒΊࠐΜͰbase64Τϯίʔυ
GitHubͷղ๏ idʹܕใຒΊࠐΜͰbase64Τϯίʔυ
GitHubͷղ๏ idʹܕใຒΊࠐΜͰbase64Τϯίʔυ