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

GraphQLサーバを作る苦しみと解決手法

 GraphQLサーバを作る苦しみと解決手法

mackee

July 21, 2020
Tweet

More Decks by mackee

Other Decks in Technology

Transcript

  1. GraphQLαʔόΛ࡞Δۤ͠Έ
    ͱղܾख๏
    @mackee_w a.k.a macopy 2020-07-21 ٢঵ࣉ.pm23

    View Slide

  2. ࿩͢͜ͱ
    • ΋ͱ΋ͱGraphQLʹջٙతͩͬͨਓ͕
    • GraphQL͕͢Ͱʹ࢖ΘΕ͍ͯΔϓϩδΣΫτͰͪΐͬͱۤ͠Έ
    • ࡞Γ௚ͧ͢ʂͱͳͬͨͱ͖ʹ·ͨGraphQLΛ࢖͏ཧ༝

    View Slide

  3. macopy
    *ʮ ߏ଄ମҠ͠ସ͑ۀʯ
    * WebΞϓϦέʔγϣϯΤϯδχΞ
    * ୲౰͸αʔόαΠυ(Perl/Go)
    * Ϛελσʔλ؅ཧ͕ಘҙͰ͕͢࠷
    ۙ͸ͦ͏͍͏࢓ࣄ͕͋Γ·ͤΜ

    View Slide

  4. ࠷ۙͷ͓࢓ࣄ

    View Slide

  5. ࠓ೔ͷओ୊
    GraphQL

    View Slide

  6. ΋͔ͯ͠͠٢঵
    ࣉpmʹGraphQL
    ͷ೾͕དྷ͍ͯ
    Δʁʁʁ

    View Slide

  7. GraphQL͓͞Β͍
    • Web޲͚ΫΤϦݴޠ
    • ಉ͡໾ׂΛ͢Δ΋ͷ: OpenAPI, gRPC, JSON-RPC…
    • GitHubͳͲͷWeb APIͰ࠾༻ྫ͋Γ
    • `/graphql`Έ͍ͨͳ୯ҰͷΤϯυϙΠϯτʹΫΤϦΛ౤͛Δ
    • Ϩεϙϯε͸JSON͕Α͘࢖ΘΕΔ(͕ɺผʹԿͰ΋ྑ͍͸ͣ)

    View Slide

  8. GraphQLΛ࢖͏ͱ͖ͷྲྀΕ
    εΩʔϚ
    ΫΤϦ
    ม਺
    Ϩεϙϯε
    POST /graphql

    View Slide

  9. GraphQLɺԿ͕͏Ε͍͠ͷʁ
    • ܕ͕͋ͬͯૉ੖Β͍͠
    • ܕ໊ʹ`!`͕ͭ͘ͱnot nullable
    • ඞཁͳfieldͷߜΓࠐΈ΍ɺҰॹʹऔΓ͍ͨϦιʔεͷҰׅऔಘ΋Ͱ͖Δ
    • ࣹӨ΍batch requestΈ͍ͨͳ࢓૊ΈΛ࡞Γࠐ·ͣʹࡁΉ
    • पลπʔϧ/ϥΠϒϥϦ͕͍ͬͺ͍͋ͬͯૉ੖Β͍͠
    • GraphiQL, apollo-client/apollo-server ͳͲͳͲ

    View Slide

  10. ͜ͷ”͏Ε͍͠”͸
    ୭ͷࢹ఺͔ʁ

    View Slide

  11. αʔό(Perl)୲౰ͷࢲࢹ఺ͰݟΔͱ

    View Slide

  12. GraphQLɺԿ͕͏Ε͍͠ͷʁ
    • ܕ͕͋ͬͯૉ੖Β͍͠
    • ܕ໊ʹ`!`͕ͭ͘ͱnot nullable
    • ඞཁͳfieldͷߜΓࠐΈ΍ɺҰॹʹऔΓ͍ͨϦιʔεͷҰׅऔಘ΋Ͱ͖Δ
    • ࣹӨ΍batch requestΈ͍ͨͳ࢓૊ΈΛ࡞Γࠐ·ͣʹࡁΉ
    • पลπʔϧ/ϥΠϒϥϦ͕͍ͬͺ͍͋ͬͯૉ੖Β͍͠
    • GraphiQL, apollo-client/apollo-server ͳͲͳͲ
    ←ͤ΍ͳͰ΋αʔόɺPerl΍ͶΜ…
    ɹundefେ׻ܴ΍ͶΜ…
    ↑͑ɺͭ·Γൃߦ͞ΕΔSQL͕ݻఆͰ͖ͳ͍ʁʁ
    ɹࠔΔͷͰ͸ʁʁʁ
    ↑ͦΕPerlʹ͋Δͷʁʁʁʁʁ

    View Slide

  13. GraphQLΛຊ֨తʹ࢖͏લ·Ͱͷҹ৅(1)
    • ΫϥΠΞϯτଆͷૢ࡞ͰσʔλͷऔΓग़͠ํ͕ಈతʹมΘΓ͏Δͷ͸ड
    ͚ೖΕ͕͍ͨ
    • ύϑΥʔϚϯενϡʔχϯά͕͔ͳΓ೉͍͠
    • RESTful APIʹൺ΂ͯGraphQLͰN+1ͷղܾ͕೉͍͠࿩͸͕͜͜ΩϞ
    ͩͱࢥΘΕΔ
    • RESTful APIͰฦ͢σʔλͷܗ͕ҰఆͩͱܾΊଧͪνϡʔχϯάͰ͖
    Δ GraphQL͸ͦΕ͕ग़དྷͳ͍

    View Slide

  14. GraphQLΛຊ֨తʹ࢖͏લ·Ͱͷҹ৅(2)
    • GitHub API v4(GraphQL)͕ग़ͨͱ͖ʹΘʔ͍ͱ৮ͬͯΈͨͱ͖ͷײ૝
    • GraphQLݴޠΛ֮͑Δͷ͕೉ղ(ʹݟ͑ͨ)
    • ୯ͳΔJSONͷ೿ੜͰ͸ͳ͍ಠࣗDSL
    • ͪΐͬͱෳࡶͰωετ͕ਂͯ͘ྔ͕ଟ͍ΫΤϦΛൃߦ͢Δͱ500͕ฦ͖ͬͯͨ
    • ʮGitHubͰ͢Β͜͏ͳΔΜ͔ͩΒզʑʹ͸…ʯ
    • ͨͿΜࠓ͸ComplexityΛܭࢉͯ͠200Ͱฦͤͳ͍Αͱݴͬͯ͘ΔͷͰ͸ͳ͍͔

    View Slide

  15. ๻͕ٕज़બ୒͢ΔͳΒબ͹ͳ͍ͩΖ͏…

    View Slide

  16. ԑ͕ͳ͍ͱࢥ͍͕ͬͯͨɺ͔͠͠…

    View Slide

  17. ࠓ೥಄ʹҟಈͨ͠
    ςʔϚʮࠓ೥ͷલ൒ͷ׆ಈΛৼΓฦΔʯ

    View Slide

  18. ҟಈ௚ޙͷձ࿩
    • ʮͳΜ͔͜ͷϖʔδදࣔ͞ΕΔ·Ͱॏ͍͠ɺαʔό΋͘͢͝CPU৯͏
    ΜͰ͢ΑͶʯ
    • ๻ʮͲΕͲΕݟͯΈΔ͔…͋͋׳Ε਌͠ΜͩPerlͩ…ʯ
    •ʮ͸ͬɺGraphQLͩ…ʯ

    View Slide

  19. ॏ͍ϖʔδΛνϡʔχϯά͢Δ
    • ͜ͷ࣌఺Ͱ͸Կ͕ݪҼ͔͸Θ͔Βͳ͍
    • GraphQLͰ͸ͳ͘ɺΞϓϦέʔγϣϯϩδοΫͷํʹݪҼ͕͋Δ͔΋
    • WebΞϓϦαʔόͷCPUΛ৯͏࣌఺ͰDBͰ͸ͳ͍
    • …͔͜͠͠ͷ୊ࡐͷൃදͰ͜͜ʹॻ࣌͘఺ͰΦν͕ݟ͍͑ͯΔ
    • ͳʹ͸ͱ΋͋ΕͦͷϖʔδͰୟ͔Ε͍ͯΔAPIΛൈ͖ग़ͯ͠ϑϨʔϜάϥ
    ϑΛग़ͧ͢

    View Slide

  20. Devel::NYTProfͷ݁Ռ
    • ԣ͕࣠࣌ؒͰॎ͕ίʔϧελοΫ
    • ͖Ε͍ͳϏϧ͕ݐͬͨ
    • ΞϓϦέʔγϣϯϩδοΫ͸੺
    ؙ͍ͷ෦෼
    • Ϗϧ͕ݐͬͯΔͷ͸Resolverͱݺ
    ͹ΕΔfieldΛղܾ͢ΔϝιουΛ
    ࠶ؼతʹ୳͍ͯ͠Δ෦෼

    View Slide

  21. PerlͷGraphQL.pm
    • ࠷ઌ୺ͷϞμϯPerl
    • Function::Parameters
    • Return::Type
    • ܕ͕ΨνΨνʹॻ͔Ε͍ͯΔ
    • ͔͠͠Perl͸ಈతܕ෇͚ݴޠͳͷͰಈతʹ
    ܕνΣοΫ͠·͢
    • ↑͕͜͜ϘτϧωοΫʹͳΔ
    • ܕνΣοΫΛແޮԽ͢ΔΑ͏ʹ
    Function::ParametersΛ͍͡ΔͱΫΤϦ୯Ґ
    Ͱݟͯ3ഒߴ଎Խ͞Εͨ

    View Slide

  22. GraphQL APIͷߴ଎ԽͷҊ
    • GraphQL.pm͓ΑͼFunction::ParametersΛ͍ͬͯ͡Pull RequestΛग़͢
    • ܕνΣοΫແޮԽ͸ຊମΛ͍͡Δ͔͠ແ͍
    • ͕ɺ͜ͷPull Request͕Authorʹཧղ͞ΕΔࣗ৴͕ͳ͍…͋ͱͬ͞͞ͱղܾ͍ͨ͠
    • Ωϟογϡ͢Δ
    • GraphQLͰ࢖ΘΕΔresolver΍Ϧιʔε୯ҐͷΩϟογϡͰ͸ແҙຯ
    • GraphQLΛύʔεͨ࣌͠఺Ͱෛ͚͕֬ఆ͍ͯ͠Δ
    • GraphQLΛGraphQL.pmͰύʔε͢ΔલʹϨεϙϯεΩϟογϡΛฦ͢ => ࠾༻

    View Slide

  23. GraphQL͸Ωϟογϡ͕ࠔ೉ͱ͍͏ᷚ
    • ΤϯυϙΠϯτ͸1Օॴ, ΫΤϦ͸bodyʹ٧ΊΒΕ͍ͯΔͷͰ…
    • query stringʹΫΤϦΛೖΕͯϨεϙϯεΩϟογϡ͢Δख๏ͳͲ
    ΋͋ΔΒ͍͠
    • nginxͰ͸ͳ͘Perlʹདྷ͔ͯΒΩϟογϡ͢Δ͜ͱʹ͠ɺBody͸ಡΉ
    • ͔͠͠BodyΛGraphQLͱͯ͠ಡΉͱෛ͚ͳͷͰGraphQLͱͯ͠ಡ
    ·ͳ͍

    View Slide

  24. ΫΤϦΛϋογϡԽͨ͠΋ͷΛredisͰ
    ϨεϙϯεΩϟογϡ
    ※ηογϣϯͳͲߟྀ͢Δͱ͔,$variables΋normalize͢ΔͳͲ΋͏গ͠޻෉͕ඞཁ

    View Slide

  25. CPUͷεύΠΫ͕؇࿨͞Εͯ
    ΊͰͨ͠ΊͰͨ͠

    View Slide

  26. ୈೋষ
    ͜ͷମݧΛͨ͠ਓ͕ؒ
    શ෦࡞Γ௚͠Λ΍Δͱ͖ʹ
    ·ͨGraphQLΛબ΂Δ͔

    View Slide

  27. શ෦࡞Γ௚͠ͷܦҢ
    • ͜ͷGraphQLΛ࢖͍ͬͯΔ෦෼͸ɺͦΕൈ͖ʹͯ͠΋͔ͳΓࠐΈೖͬ
    ͨϩδοΫ͕ೖ͍ͬͯΔ
    • νʔϜ಺Ͱ΋ཧղͰ͖͍ͯΔਓ͕গͳ͍
    • ͔͠͠αʔϏεͷ֩ͷ෦෼ͳͷͰ࢓༷มߋ΍ػೳ௥ՃΛόϯόϯೖΕ
    ͍ͨ
    • ͔ͳΓͰ͔͍ػೳ௥ՃΛ͍ͨ͠ => ࡞Γ௚͔͢…

    View Slide

  28. ࡞Γ௚͍ͭ͢ͰʹGraphQLΛ˓˓͍ͨ͠
    • ݱঢ়ͷ࢓૊Έ͸ෳࡶͳGraphQLΫΤϦΛॻ͘ͱWebαʔό͕ॏ͘ͳΔ
    ಛੑ
    • ΩϟογϡͰ͖Δͷ΋ඇϩάΠϯϢʔβͰϦΞϧλΠϜੑ͕ແ͍಺༰ͩ
    ͚Ͱݶք͕͋Δ
    • ͦ΋ͦ΋GraphQLΛ˓˓ͯ͠ղܾ͍ͨ͠
    • ○○ʹ͸ʮ΍ΊΔʯͱ͔ʮҡ࣋ͨ͠··࢓૊ΈΛม͑Δʯͱ͔ͦͷ΁
    Μ͕ೖΓ·͢

    View Slide

  29. ࡞Γ௚͢ଞͷཁҼ
    • ύϑΥʔϚϯεཁ͕݅ଞͷ෦෼ͱҧ͏
    • ि຤ͳͲʹਓ͕ϫοͱདྷͨΒ࢖ΘΕΔ͕ීஈ͸શ͘࢖ΘΕͳ͍
    • ࠷ۙ͸ਓ͕૿͑ͯDBෛՙ΋ؾʹͳΓ࢝Ίͨ

    View Slide

  30. GraphQL͸ے͕ѱ͍ͷ͔ʁ
    • ͜ͷ࿩͚ͩฉ͘ͱʮ΍ͬ΂ۙدΒΜͱ͜ʯͬͯࢥ͏ਓ΋͍Δ͔΋
    • ੾Γ෼͚ͯߟ͑Δ
    • ݱঢ়ͷ࢓૊ΈΑΓ΋͍͍ղ๏͕͋Δͷ͔
    • ͦΕͱ΋
    • GraphQLࣗମ͕ۤ࿑ʹରͯ͠Ϧλʔϯ͕߹ͬͯͳ͍ͷ͔

    View Slide

  31. WebϑϩϯτΤϯυଆͷਓʹҙݟΛฉ͍ͯΈΔ
    • ʮ͢Ͱʹ։ൃ͕͜ͳΕ͖͍ͯͯΔʯʮπʔϧνΣΠϯͷϊ΢ϋ΢΋ཷ·ͬͯ
    ͍Δʯ
    • ͦ΋ͦ΋ϑϩϯτΤϯυଆ͸TypeScriptΛશ໘తʹ࠾༻͍ͯͯ͠GraphQLͱ
    ૬ੑ͕ྑ͍
    • ੈؒʹࣄྫ͕ᷓΕ͍ͯΔ૊Έ߹Θͤ
    • ୅ҊͷgRPC(Web͔Gateway)ͩͱ࢓૊Έ͔Βߏங͢Δ͜ͱʹͳΔ
    • ʮWebϑϩϯτΤϯυଆͷਓ͕GraphQLҎ֎Λ࠾༻͢Δಈػ͸ͳͦ͞͏ʯ

    View Slide

  32. ಄ΛϦηοτͯ͠GraphQLΛ͏·͘αʔόͰѻ
    ͏͜ͱΛߟ͑Δ
    • Perlͷ··͍͘ͷ͸೉ͦ͠͏
    • ௚઀ѻ͏ʹ͸GraphQL.pm΄΅Ұ୒ͳͷͰ
    • खલʹapollo-serverཱͯͯREST APIͱ૬ޓม׵͢ΔͷͳΒ…
    • Go͸ࣄྫ͕গ͚ͩ͋͠ΔͬΆ͍ ϥΠϒϥϦ΋͍͔ͭ͋͘Δ
    • TypeScriptͰ࢖͑Δ੩తܕͷϝϦοτ΋GoͳΒड͚ΒΕΔ

    View Slide

  33. ͔͠͠GraphQLͷαʔόΛ࡞Δ͜ͱࣗମͷ໰୊
    ΋͋Δ
    • DBʹରͯ͠N+1ΫΤϦ
    • ωετͨ͠ΓෳࡶͳΫΤϦΛೖΕΒΕͨͱ͖ʹDoSΈ͍ͨʹͳΒͳ͍
    ͔
    • Ωϟογϡ೉͍͠໰୊
    • etc…etc…

    View Slide

  34. ͔͠͠GraphQLͷαʔόΛ࡞Δ͜ͱࣗମͷ໰୊
    ΋͋Δ
    • DBʹରͯ͠N+1ΫΤϦ
    • ωετͨ͠ΓෳࡶͳΫΤϦΛೖΕΒΕͨͱ͖ʹDoSΈ͍ͨʹͳΒͳ͍
    ͔
    • Ωϟογϡ೉͍͠໰୊
    • etc…etc…
    Ұճۤ࿑ͨ͠͠
    ͳΜͱ͔ͳΔ͔ͳͱࢥͬͨ

    View Slide

  35. ҰͭҰͭղܾ͍ͯ͘͠աఔ

    View Slide

  36. GraphQLύʔαʔ/Resolver => gqlgen
    • εΩʔϚ͔ΒResolverΛࣗಈੜ੒͢ΔϥΠϒϥϦ

    View Slide

  37. N+1ͷղ๏ => vektah/dataloaden
    • ӈͷ໰͍߹Θͤϓʔϧ
    ͷ෦෼Λࣗಈੜ੒͢Δ
    ϥΠϒϥϦ
    • Ұఆ࣌ؒ಺ͷಉ͡ςʔ
    ϒϧʹର͢ΔΫΤϦΛ
    ·ͱΊΒΕΔ

    View Slide

  38. ෳࡶͳΫΤϦʹର͢Δख๏
    • Query Complexity
    • ΫΤϦͷResolverΛ࣮ߦ͢Δલʹॏ͍ΫΤϦ͡Όͳ͍͔ௐ΂Δ
    • ۩ମతʹ͸ϖʔδϯάΛڧ੍͢ΔͳͲͯ͠औಘ͢Δ࠷େ݅਺ΛΫΤϦ
    Ͱ֬ఆͤ͞Δ => ᮢ஋Λ΋͏͚ͯ஄͘
    • ϖʔδϯάܗࣜ => Relay Server Specification
    • Ҿ਺΍ϨεϙϯεܗࣜʹσϑΝΫτελϯμʔυ͕͋ΔͷͰ͜ΕΛ࢖͏

    View Slide

  39. ͜ͷลͷ࢓૊ΈͰٙ໰͸ղফͯ͠
    ࠓ͸ຊ൪౤ೖʹ޲͚ͯಈ͍͍ͯΔͱ͜Ζ

    View Slide

  40. ͜͜ͰҰ۟
    ྑༀ͸
    ɹɹޱʹۤ͠
    ɹɹɹɹGraphQL

    View Slide

  41. ·ͱΊ
    • GraphQLʹର͢Δ఍߅ײ͸Կͩͬͨͷ͔͕গ͠Θ͔ͬͨ
    • ͨͿΜࠓ·Ͱͷαʔόͷ࡞ΓํΛ੍ݶ͢Δ࢓༷
    • ৽͍͠ύϥμΠϜͱ͢ΔͱɺڵຯΛ࣋ͬͯऔΓ૊Ίͨ
    • ৽͍ٕ͠ज़Λ࠾༻͢Δ͜ͱ͸ɺͦͷٕज़ͷະདྷʹϕοτ͢Δ͜ͱ
    • ϕοτ͢Δͱ͍͏͜ͱ͸ɺ͍͟ͱͳΕ͹OSSʹPull RequestΛग़ͨ͠Γɺϓ
    ϩδΣΫτ಺ʹ޿ΊΔΑ͏ͳओମతͳಈ͖͕ٻΊΒΕΔ
    • ͜͏΍ͬͯࣄྫΛग़͢ͷ΋ߩݙ͔΋͠Εͳ͍ͱࢥͬͯ΍ͬͯ·͢

    View Slide

  42. ͓·͚

    View Slide

  43. ͭΒ͍΍ͭ: root queryͷnode
    • Relay Server Specificationʹྫࣔ͞Εͯ
    ͍Δ΍ͭ
    • ผʹඞਢͰ͸ͳ͍͕ɺΫϥΠΞϯτଆ͸
    ͋Δͱศར
    • ΫϥΠΞϯταΠυͷΩϟογϡߋ৽ͷ
    ͨΊʹNodeͩͬͨΒͳΜͰ΋ฦͤΔ΍ͭ
    • αʔόαΠυ͸`ID`͚ͩͰͲͷܕ͔Λ൑ఆ
    ͠ͳ͚Ε͹ͳΒͳ͍

    View Slide

  44. GitHubͷղ๏
    idʹܕ৘ใຒΊࠐΜͰbase64Τϯίʔυ

    View Slide

  45. GitHubͷղ๏
    idʹܕ৘ใຒΊࠐΜͰbase64Τϯίʔυ

    View Slide

  46. GitHubͷղ๏
    idʹܕ৘ใຒΊࠐΜͰbase64Τϯίʔυ

    View Slide