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
Agentに至る道 〜なぜLLMは自動でコードを書けるようになったのか〜
mackee
5
2.4k
今!ソフトウェアエンジニアがハードウェアに手を出すには
mackee
14
5.5k
ワンバイナリWebサービスのススメ
mackee
10
8.1k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
130
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
1k
perl for shell, awk and sed programmers
mackee
3
2.6k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
1k
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
910
マイクロサービス化を利用した Goへの移行事例
mackee
0
1k
Other Decks in Technology
See All in Technology
.NET 10のASP. NET Core注目の新機能
tomokusaba
0
140
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.2k
不確実性に備える ABEMA の信頼性設計とオブザーバビリティ基盤
nagapad
4
9.1k
命名から始めるSpec Driven
kuruwic
1
580
日経電子版の BCP への取り組みについて/mediajaws1121
nikkei_engineer_recruiting
0
100
AWS re:Invent 2025 で頻出の 生成 AI サービスをおさらい
komakichi
3
250
[続・営業向け 誰でも話せるOCI セールストーク] AWSよりOCIの優位性が分からない編(2025年11月21日開催)
oracle4engineer
PRO
1
150
TypeScript×CASLでつくるSaaSの認可 / Authz with CASL
saka2jp
2
150
AI開発の定着を推進するために揃えるべき前提
suguruooki
1
430
ABEJA FIRST GUIDE for Software Engineers
abeja
0
3.2k
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.3k
type-challenges を全問解いたのでエッセンスと推し問題を紹介してみる
kworkdev
PRO
0
120
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
Facilitating Awesome Meetings
lara
57
6.6k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
How GitHub (no longer) Works
holman
315
140k
Statistics for Hackers
jakevdp
799
230k
YesSQL, Process and Tooling at Scale
rocio
174
15k
What's in a price? How to price your products and services
michaelherold
246
12k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
A designer walks into a library…
pauljervisheath
210
24k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
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Τϯίʔυ