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.9k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
110
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
800
perl for shell, awk and sed programmers
mackee
2
2.4k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
770
database/sqlでNullを扱う歴史とsql.Null[T]の登場 / sql.Null[T] history
mackee
0
660
マイクロサービス化を利用した Goへの移行事例
mackee
0
790
PerlでつくるフルスクラッチWebAuthn/パスキー認証 / Demonstration of full-scratch WebAuthn/Passkey Authentication written in Perl
mackee
3
4.9k
SRE定例やその辺の取り組みをアプリケーションエンジニア目線で語る / "Observe" about SRE Meeting by Application Engineer
mackee
0
2k
Other Decks in Technology
See All in Technology
【OptimizationNight】数理最適化のラストワンマイルとしてのUIUX
brainpadpr
0
130
生成AI導入の効果を最大化する データ活用戦略
ham0215
0
110
SRE新規立ち上げ! Hubbleインフラのこれまでと展望
katsuya0515
0
160
モバイルゲームの開発を支える基盤の歩み ~再現性のある開発ラインを量産する秘訣~
qualiarts
0
1.1k
Agent Development Kitで始める生成 AI エージェント実践開発
danishi
0
120
Claude Codeは仕様駆動の夢を見ない
gotalab555
0
130
Findy Freelance 利用シーン別AI活用例
ness
0
290
製造業の課題解決に向けた機械学習の活用と、製造業特化LLM開発への挑戦
knt44kw
0
150
データ基盤の管理者からGoogle Cloud全体の管理者になっていた話
zozotech
PRO
0
320
Tableau API連携の罠!?脱スプシを夢見たはずが、逆に依存を深めた話
cuebic9bic
3
210
オブザーバビリティプラットフォーム開発におけるオブザーバビリティとの向き合い / Hatena Engineer Seminar #34 オブザーバビリティの実現と運用編
arthur1
0
340
AI関数が早くなったので試してみよう
kumakura
0
110
Featured
See All Featured
Adopting Sorbet at Scale
ufuk
77
9.5k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Optimizing for Happiness
mojombo
379
70k
[RailsConf 2023] Rails as a piece of cake
palkan
56
5.7k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.3k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Agile that works and the tools we love
rasmusluckow
329
21k
Java REST API Framework Comparison - PWX 2021
mraible
32
8.8k
Docker and Python
trallard
45
3.5k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
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Τϯίʔυ