Webアプリケーションにおける並行処理の難しさ / #Gocon_Sendai

7f68f5f85f4a39df7d8d3c81cbbfb788?s=47 ぷらす
October 10, 2020

Webアプリケーションにおける並行処理の難しさ / #Gocon_Sendai

Go Conference ’20 in Autumn SENDAIの登壇資料です。

Goの魅力の1つは並行処理です。goroutineやchannelを使うことで簡単に並行処理を記述することができます。しかし、その簡単な文法とは裏腹に、実際のアプリケーションに並行処理を組み込もうとすると、思ったように実装できなかったり、必要以上に複雑な設計になってしまった経験は無いでしょうか?

このセッションでは、音楽の再生管理を行うWeb APIサーバを1から作る上で、設計で悩んだポイントやハマった実装を紹介します。実際の開発での事例を紹介することで、今後皆さんが並行処理を使った実装する手助けになれば幸いです。

7f68f5f85f4a39df7d8d3c81cbbfb788?s=128

ぷらす

October 10, 2020
Tweet

Transcript

  1. 8FCΞϓϦέʔγϣϯʹ ͓͚Δฒߦॲཧͷ೉͠͞ (P$POGFSFODF`JO"VUVNO4&/%"* /BPLJ,JTIJ !QBTT 

  2. ͯ͞ɺօ͞Μ 

  3. ฒߦॲཧ΍ͬͯ·͔͢ʁ ! 

  4. ฒߦॲཧਏ͍Ͱ͔͢ʁ " 

  5. ๻͸ਏ͔ͬͨͰ͢ 

  6. ࠓ೔͸ͦͷਏ͞ʹͲ͏ରॲ͔ͨ͠ ʹ͍ͭͯ঺հ͠·͢ 

  7. ࠓ೔ͷτʔΫ ˔ ಺༰ ฒߦॲཧͰϋϚͬͨ໰୊ʹͲ͏Ξϓϩʔν͍͔ͯͬͨ͠ ˓ 8FCΞϓϦέʔγϣϯ "1* Λ୊ࡐʹ ˓ ίʔυͷ࿩ΑΓɺઃܭ΍ߟ͑ํͷ࿩͕ϝΠϯ

    ˔ Ϩϕϧײ #FHJOOFSd*OUFSNFEJBUFΛ૝ఆ ˓ (Pͷجຊจ๏͸લఏ஌ࣝͱ͠·͢ ˓ HPSPVUJOF΍DIBOOFMͷجຊతͳ࢖͍ํ΋લఏ஌ࣝͱ͠·͢ 
  8. ࣗݾ঺հ /BPLJ,JTIJ  ˔ (Pྺ೥ ˔ (P$POGFSFODFྺճ ௌߨ ˔ ژ౎େֶ

    ޻ֶ෦ ˔ $".1)03୅ද !QBTT
  9. 

  10. 

  11. "HFOEB  ฒߦॲཧͷԿ͕ਏ͍ʁ  ୊ࡐͱͳΔฒߦॲཧΛ࢖ͬͨ8FCΞϓϦέʔγϣϯ  ϋϚͬͨͱ͜Ζ  ·ͱΊ 

  12. ฒߦॲཧͷԿ͕ਏ͍ʁ 

  13. શମ೺Ѳͷ೉͠͞ ˔ ඞͣ͠΋ιʔείʔυͷ্͔Βॱʹ࣮ߦ͞Εͳ͍ ˔ ͋Δ࣌఺ͰͲͷHPSPVUJOF͕ىಈ͍ͯ͠Δ͔೺Ѳͮ͠Β͍ ˔ ෳ਺ͷHPSPVUJOFΛಉ࣌ʹ೺Ѳ͢Δඞཁ͕͋Γೝ஌ෛՙߴ  ༁Θ͔ΒΜ

  14. HPSPVUJOFηʔϑͷ୲อ ˔ ෳ਺ͷHPSPVUJOF͔Βม਺Λಉ࣌ʹಡΈॻ͖ͯ͠΋໰୊ͳ͍ঢ়ଶ ˓ ଞͷݴޠͰ͸ʮεϨουηʔϑʯͱ΋ݴ͏ ˔ DIBOOFM΍TZOD.VUFYΛ࢖ͬͯHPSPVUJOFηʔϑʹ͠Α͏ͱࢼΈΔ ˓ ࡉ͔͍ม਺Ͱରࡦ࿙Ε͕ͪ͠ 

    ͍ͭͷؒʹ͔஋͕ ॻ͖׵ΘͬͯΔ
  15. DIBOOFMͷϒϩοΩϯά ˔ DIBOOFMʹ༰ྔҎ্ͷ஋Λૹ৴͠Α͏ͱ͢ΔͱϒϩοΫ͞ΕΔ ˔ DIBOOFM͕ҲΕΔͱҙਤͤͣϒϩοΩϯά͕ൃੜ͢ΔՄೳੑ ˓ ϦΫΤετ਺͕গͳ͍ͱݦࡏԽ͠ʹ͍͘  ٸʹΞϓϦέʔγϣϯࢭ ·ͬͨΜ͚ͩͲ

  16. ͜Εશ෦ϋϚΓ·ͨ͠ 

  17. Ͳ͏ཱͪ޲͔͔ͬͨʁ 

  18. ͦͷલʹ 

  19. ୊ࡐͱͳΔฒߦॲཧΛ ࢖ͬͨΞϓϦέʔγϣϯ 

  20. ৽͍͠Իָͱग़ձ͏ָ͠͞Λ͋ͳͨʹ

  21. 3FMBZN  ϦϞʔτϫʔΫதͷ࡞ۀ༻#(.Λ 4/4Ͱืू ༑ୡͱͷυϥΠϒதʹྲྀ͢ۂΛ ֤ʑͷεϚϗ͔Βࣗ༝ʹ௥Ճ օ͕ௌָ͖͍ͨۂΛͭͷεϐʔΧʔͰָ͠ΊΔ8FCΞϓϦ

  22. 3FMBZNͷಛ௃ օ͕ௌָ͖͍ͨۂΛͭͷεϐʔΧʔͰָ͠ΊΔ8FCΞϓϦ 

  23. 3FMBZNͷ։ൃ ˔ ֶੜͷʮझຯ։ൃʯ ˔ 044Ͱ։ൃ ˓ IUUQTHJUIVCDPNDBNQIPSSFMBZNTFSWFS ˓ IUUQTHJUIVCDPNDBNQIPSSFMBZNDMJFOU ˔

    ࢖༻ٕज़(P 7VF 
  24. 3FMBZNʹ͓͚Δʮηογϣϯʯ ˔ ͭͷ࠶ੜΛද͢୯Ґ ˓ /ਓͷϢʔβʢࢀՃऀʣ͕ηογϣϯʹࢀՃͰ͖Δ ˓ .ۂָۂΛ௥ՃͰ͖Δ  ͜Ε͕ηογϣϯ ˞ηογϣϯʹΧϥΦέϧʔϜͱߟ͑Δͱཧղ͠΍͍͔͢΋

  25. ฒߦॲཧΛ࢖͍ͬͯΔՕॴ 

  26. ࢀՃऀಉ࢜ͷϦΞϧλΠϜಉظ ˔ ۂͷ௥Ճɺ࠶ੜ։࢝౳ͷΠϕϯτΛશͯͷ୺຤ʹ൓ө͍ͤͨ͞ ˔ 8FC4PDLFUΛ࢖࣮ͬͯݱ ˓ 4FSWFSˠ$MJFOU 

  27. ηογϣϯͷ࠶ੜঢ়گͷ؅ཧ  ˔ ࠶ੜঢ়گͷมԽΛ؂ࢹ ˔ ηογϣϯʹHPSPVUJOF ˔ Πϕϯτ͸8FC4PDLFUͰ഑৴

  28. ۂͷ࠶ੜ͕ऴྃͨ͠λΠϛϯάͰ%#ͷߋ৽΍Πϕϯτͷ഑৴Λ͍ͨ͠ ͳͥηογϣϯ؅ཧHPSPVUJOF͕ඞཁͳͷ͔ʁ  ΞϓϦέʔγϣϯଆͰλΠϚʔΛ࣋ͬͯ࠶ੜऴྃΛݕ஌͢Δ͜ͱʹ ˔ 4QPUJGZ8FC"1*ʹ͸8FCIPPL͕ͳ͍ ˔ ʮ͍ͭۂͷ࠶ੜ͕ऴ͔ྃͨ͠ʯΛ஌Δ͢΂͕ͳ͍

  29. ϋϚͬͨͱ͜Ζ 

  30. ࿈ଧ͢Δͱฦͬͯ͜ͳ͘ͳΔ"1* 

  31. ࿈ଧ͢Δͱฦͬͯ͜ͳ͘ͳΔ"1* ˔ ָۂͷεΩοϓૢ࡞Λߦ͏ΤϯυϙΠϯτ ˓ ୟ͘ͱ࣍ͷۂʹભҠ͢Δ ˔ NT͓͖ʹλοϓͨ͠Β໰୊ͳ͘ಈ࡞ ˔ ௒଎࿈ଧͨ͠ΒϨεϙϯε͕ฦͬͯ͜ͳ͘ͳΔ 

  32. 

  33. εΩοϓ"1*ͷ࣮૷Λ෼ੳ εΩοϓ"1*͸ඇಉظͰηογϣϯͷ࠶ੜঢ়گΛߋ৽  ηογϣϯऴྃঢ়ଶͳΒ#BE3FRVFTUͯ͠SFUVSO  4QPUJGZ8FC"1*Λୟ͍ͯۂΛεΩοϓ  TLJQ$Iͱ͍͏DIBOOFMΛ௨ͯ͡ɺηογϣϯ؅ཧHPSPVUJOFʹ "1*͕ݺ͹Εͨ͜ͱΛૹ৴ B

    λΠϚʔͷ࣌ؒΛϦηοτ͢Δඞཁ͕͋Δ  "DDFQUFE )BOEMFSHPSPVUJOF͸ऴྃ 
  34. DIBOOFMͷૹ৴͕ոͦ͠͏ 

  35. HPSPVUJOFͷϥΠϑαΠΫϧΛ ҙࣝͯ͠ DIBOOFMͷ௨৴Λௐࠪ͢Δ 

  36. HPSPVUJOFͷϥΠϑαΠΫϧΛҙࣝ͢Δ ˔ HPSPVUJOF͕ʮ͍ͭ։࢝͞ΕΔ͔ʯʮ͍ͭऴྃ͢Δ͔ʯΛߟ͑Δ ˔ DIBOOFMͷૹ৴࣌ʹHPSPVUJOF͕ੜ͖͍ͯΔ͔Ͳ͏͔Λߟ͑Δ ϥΠϑαΠΫϧΛҙࣝ͢ΔͱDIBOOFMͷόάΛൃݟ͠΍͍͢ 

  37. ؆୯ͳྫ ˔ HPSPVUJOF#͸͍ͭૹ৴ͯ͠΋ྑ͍ ˔ HPSPVUJOF"͸ૹ৴Ͱ͖ͳ͍৔߹͕͋Δ "ˠ#ʹૹ͍ͬͯΔίʔυ͕ ͋Ε͹όάͷةݥ 

  38. ࣮ࡍʹߟ͑ͯΈΔ 

  39. TLJQ$Iͷड͚औΓଆͰߦ͍ͬͯͨॲཧ ड͚औΓଆ͸ηογϣϯ؅ཧHPSPVUJOF ˔ ࣍ʹ࠶ੜ͢Δۂ͕ଘࡏ͢Δ৔߹  ࣍ͷۂΛ4QPUJGZͷΩϡʔʹ௥Ճ ˔ શͯͷۂͷ࠶ੜ͕ऴΘͬͨ৔߹  ηογϣϯΛऴྃঢ়ଶʹભҠɺ%#Λߋ৽

     શͯͷ୺຤ʹηογϣϯऴྃΠϕϯτΛૹ৴  HPSPVUJOFΛऴྃ ˡո͍͠ 
  40. ˔ ͷεΩοϓͰηογϣϯ͕ऴྃ ˔ ʙ/ͷεΩοϓॲཧ͸DIBOOFM͕ ͦͷ͏ͪҲΕ్ͯத͔ΒϒϩοΫ Կ͕ى͍͔ͬͯͨ͜  )BOEMFS͕ϒϩοΫ͞Ε Ϩεϙϯε͕ฦΒͳ͍ࣄଶʹ

  41. ҰԠରࡦΛ͍ͯͨ͠ ˔ ࠶ੜঢ়ଶΛνΣοΫ͠ɺऴྃঢ়ଶͳΒ#BE3FRVFTUͰSFUVSO ˔ τϥϯβΫγϣϯͷϩοΫ͕͖ͪΜͱ͔͔͍ͬͯͳ͔ͬͨ ˓ εΩοϓͷঢ়ଶมߋ͕൓ө͞ΕΔલͷ࠶ੜঢ়ଶΛऔಘ͍ͯͨ͠ ˓ ߴස౓ͰϦΫΤετ͕དྷͳ͍ͱ࠶ݱ͠ͳ͍ 

  42. ࢑ఆతͳରԠ DIBOOFMͷઃܭΛม͑Δʹ͸͕͔͔࣌ؒΔͱ൑அɺ࢑ఆతͳରԠΛߦ͏ ˔ ద੾ͳϩοΫΛऔΔ ˔ εΩοϓ"1*ͷϦΫΤετഁغ ˓ 4QPUJGZ8FC"1*ͷϨεϙϯε͕஗͍ͷͰͦ΋ͦ΋࿈ଧ͞Εͨ͘ͳ͍ ˓ ࿈ଧ͞ΕͨΒ͍͔ͭ͘ͷϦΫΤετ͸ഁغͯ͠͠·͏

    
  43. εΩοϓ"1*ͷϦΫΤετഁغ DIBOOFMͷDBQҎ্ͷϦΫΤετ͸ഁغ͢Δ  func sendToSkipCh() { if len(skipCh) < cap(skipCh)

    { skipCh <- struct{}{} } }
  44. ˔ DIBOOFMपΓͷόά͕͔͋ͬͨΒͱ͍ͬͯɺDIBOOFMΛۦ࢖ͯ͠όά ͷରࡦΛ͠ͳ͍͍ͯ͘ ˔ ΋ͬͱखલͷஈ֊Ͱॲཧ͢Ε͹ɺ؆୯ʹରॲͰ͖Δ͜ͱ΋ଟ͍ ͨͩ͠ɺٕज़తʹഊ๺ײ ฒߦॲཧͷόάΛฒߦॲཧҎ֎ͷͱ͜ΖͰରࡦ 

  45. શମઃܭϨϕϧͰ ࠜຊతͳରࡦΛߟ͑ͯΈΔ 

  46. DIBOOFMͷॴ༗ݖΛߟ͑Δ ˔ ߟ͑ํͷ࿩ ʮ(PݴޠʹΑΔฒߦॲཧʯʹͯղઆ ˔ DIBOOFMΛੜ੒ͨ͠HPSPVUJOFͷΈ͕DIBOOFM΁ૹ৴Մೳ ˔ ͦͷଞͷHPSPVUJOF͸ಡΈࠐΈͷΈՄೳ ˔ DIBOOFMͷDMPTF౳ͷϋϯυϦϯά͕͠΍͍͢

     func SkipCh() <-chan struct{} { return skipCh } ϥΠϑαΠΫϧͷ୹͍ํ͕DIBOOFMͷॴ༗ݖΛ࣋ͯ͹ ૹ৴͕ϒϩοΫ͞ΕͣʹࡁΉ
  47. εΩοϓ"1*ʹ͓͚ΔTLJQ$Iͷॴ༗ݖ  ˔ /ݸͷ)BOEMFSHPSPVUJOF͔Β DIBOOFM΁ૹ৴͕ඞཁ ˔ ੜ੒ଆͰॴ༗ݖΛ࣋ͯͯͳ͍ঢ়گ ૹ৴ଆͷHPSPVUJOFͰDIBOOFMΛੜ੒ͯ͠΋ɺηογϣϯ؅ཧHPSPVUJOFʹ౉ͤͳ͍

  48. ˔ ͜͜Ͱ͸$PNNBOEFSͱ໋໊ ˔ $PNNBOEFS͕ηογϣϯ؅ཧHPSPVUJOFͷॴ༗ݖΛ࣋ͭ ˔ ηογϣϯૢ࡞͸$PNNBOEFSHPSPVUJOFΛܦ༝͢Δ ͣͬͱىಈ͍ͯ͠Δ਌HPSPVUJOFΛ༻ҙ 

  49. ˔ $PNNBOEFS͸)BOEMFSΑΓ௕ੜ͖ͳͷͰϒϩοΫ͞ΕΔ͜ͱ͸ͳ͍ ˔ )BOEMFSଆͷॲཧ͕؆୯ʹ ͜ͷํ๏ͷϝϦοτ 

  50. σϝϦοτ ˔ ࢖༻͢ΔHPSPVUJOF͕૿͑Δ෼ɺશମ૾͕೺Ѳͮ͠Β͍ ˓ ࠷ॳʹڍ͛ͨʮશମ೺Ѳͷ೉͠͞ʯ 

  51. ฒߦॲཧϞϦϞϦͰؤுΔ͔Ͳ͏͔͸νʔϜ࣍ୈ ˔ ؤுΔͳΒ ˓ શମ૾͕೺Ѳ͠ʹ͍͘෼ɺυΩϡϝϯτ౳ͷ੔උ͸ͱͯ΋ॏཁ ˓ ͖Ε͍ͳίʔυͰ͋Ε͹υΩϡϝϯτ͸ෆཁ͸͋·Γ௨͡ͳ͍ʢओ؍ʣ ˔ ͜ΕΒʹ౤ࢿ͕Ͱ͖ͳ͍ͳΒͰ͖Δ͚ͩฒߦॲཧΛආ͚Δͷ΋ख ˓

    εΩοϓ"1*ͷ࢑ఆରԠͷΑ͏ʹ΍͍ͬͯ͘ ˓ ͦΕ͚ͩͰे෼ͳέʔε΋ଟ͍ ˓ ຊ౰ʹඞཁͳͱ͜ΖͰϐϯϙΠϯτͰ࢖͍ͬͯ͘ 
  52. ·ͱΊ 

  53. ·ͱΊ ˔ 3FMBZNͷ"1*αʔόͷ࣮૷தʹฒߦॲཧؔ࿈ͰϋϚͬͨࣄྫΛ঺հ ˓ ࿈ଧ͢Δͱฦͬͯ͜ͳ͘ͳΔ"1* ˔ HPSPVUJOFͷϥΠϑαΠΫϧ΍ॴ༗ݖΛҙࣝͯ͠ઃܭ͢Δͱྑͦ͞͏ ˔ ฒߦॲཧͰϞϦϞϦͰؤுΔ͔Ͳ͏͔͸νʔϜ࣍ୈ ˓

    ؤுΔ৔߹͸͖ͪΜͱ౤ࢿ͍ͯ͘͜͠ͱ͕େࣄ ਏ͞Λ৐Γӽ͑ͯΑΓྑ͍ฒߦॲཧϥΠϑΛʂ 
  54. ࢀߟϦϯΫ ˔ 3FMBZN ˓ IUUQTSFMBZNDBNQIOFU ˔ $PODVSSFODZJTOPUQBSBMMFMJTN 5IF(P#MPH ˓ IUUQTCMPHHPMBOHPSHXB[BUBML

    ˔ (PݴޠʹΑΔฒߦॲཧ c,BUIFSJOF$PY#VEBZ ࢁޱ ೳ᫫