Go駆動開発で超速Pushエンジンを作った話

 Go駆動開発で超速Pushエンジンを作った話

Go Conference 2014 spring で発表した資料。
受託開発に持ち込んだ事例紹介。
http://connpass.com/event/6370/

Fdbc02073fe49c59f4f1ae705691a128?s=128

kadota kyohei

May 31, 2014
Tweet

Transcript

  1. Goۦಈ։ൃͰ௒଎PushΤϯδϯΛ࡞ͬͨ࿩ @plan9user GoCon 2014 spring

  2. GoΛ࢖͍͍ͨҰ৺Ͱडୗۀ຿΁࣋ͪࠐΜͩ࣌ͷ࿩

  3. ࣗݾ঺հ • ໳ଟګฏ • झຯ͸”Plan 9”Ͱ͢ʂ • Go޷͖ͳΒPlan 9ͷࢥ૝΋޷Ή͸ͣ •

    2011೥͔ΒϑΣϯϦϧͰಇ͍ͯ·͢
  4. • ͜ͳ͍ͩSleipnir 6͕ग़·ͨ͠ʂ • ڞಉ։ൃ෦ • اۀ༷͔Βͷडୗ։ൃΛߦ͏෦ॺ • ࣮੷঺հ -

    http://biz.fenrir-inc.com • Sleipnir΁ͷ͝ҙݟ͸ެࣜαΠτ͔Β ϑΣϯϦϧגࣜձࣾ
  5. • εϚʔτϑΥϯΞϓϦ։ൃ΍ͬͯ·͢ • iOS, Android • Windows 8 (एׯ) •

    ࡢ೥຤͋ͨΓ͔ΒXamarin͸͡Ί·ͨ͠ ۀ຿಺༰
  6. go? • ϓογϡ௨஌ • ࠃ಺αʔϏεͰͳ͚Ε͹×ɹͱ͔ • ࣗ෼ͰશମΛίϯτϩʔϧ͍ͨ͠ɹͱ͔ • ങ͍੾Γ͍ͨɹͱ͔

  7. push௨஌ͷ͘͠Έ 1. ΞϓϦτʔΫϯΛαʔόʹૹ৴ 2. αʔό͸อଘ͍ͯ͠ΔτʔΫϯͱϝοηʔδ Ληοτʹͯ͠APNs/GCM΁ૹ৴ 3. ϝοηʔδ͕֤୺຤΁ಧ͘ ܾͯ͠೉͘͠͸ͳ͍Μ͚ͩͲ…

  8. • ࠷ॳ͸PHPͰ࣮૷ • ਫ४Λຬͨͤͳ͍ • ਺ेສ௨஌ʹ଱͑ΒΕͳ͍ • ઃܭ͕·͔ͣͬͨ • PHPѱ͘ͳ͍

    performance problems… ඵ ඵ ඵ ඵ ඵ ສ ສ ສ ສ
  9. ͩΊͩͬͨͱ͜Ζ

  10. problem? • PHPͳͷͰฒྻԽ͕೉͔ͬͨ͠ • ೋॏૹ৴๷ࢭͷͨΊDBΛΩϡʔʹ͍ͯͨ͠ • ௨৴Τϥʔ౳ͰϦτϥΠ͢΂͖৔߹΍్த Ͱམͪͨ৔߹Λ૝ఆ • ׬ྃϚʔΫ΋DBʹ͍࣋ͬͯͨ

  11. goal? • ॲཧͷ଴ͪ࣌ؒΛͳͯ͘͠ੑೳΛ্͛Δ • ୺຤਺͕ଟ͍ͱ͖͸෼ࢄͯ͠ૹ৴͢Δ • ෳ਺ϚγϯͰͻͱͭͷγεςϜʹ͢Δ • DB΁ͷґଘΛͳ͘͢

  12. ͓΍ʁ

  13. ͜ΕGoͷग़൪͡ΌͶʁ

  14. GoΛ޷Ήཧ༝(౰࣌) • Rob Pike΍Russ Cox͕ࢀՃͯ͠Δ • Plan 9ʹ΋ؔΘ͓ͬͯΒΕ·ͨ͠ • Alef,

    Limbo͔Βଓ͘CSPྑ͍ • ඪ४ύοέʔδ΋ॆ࣮ͯͦ͠͏(งғؾ)
  15. GoͱXamarinಉ࣌౤ೖܾఆ • Α͘௨ͬͨͳͱࢥ͍·͢… • ӡ͕ྑ͘ظؒݶఆͷΞϓϦͩͬͨ • ௕ظӡ༻ͳΒอक΋ߟ͑Δඞཁ͕͋Δ • ։ൃظ͕ؒൺֱత௕͘औΕͨ •

    ࠷ॳ͸ௐ΂ͳ͕Βॻ͘ͷͰޮ཰ѱ͍
  16. GoͰॻ͘ʂ

  17. overview GSPOU GSPOU DUMS BHFOU BHFOU BHFOU rpc઀ଓ ϊʔυ(ϓϩηε)

  18. net/rpcύοέʔδ // ܾ·ͬͨܗͷϝιουΛΤΫεϙʔτ͓͍ͯͯ͠ fund (agent *Agent) Broadcast(r *Request, res *Response)

    error { return nil } ! // ผͷϊʔυ͔ΒrpcΛίʔϧ͢Δ c, _ := rpc.Dial(“net”, “localhost:17030”) err := c.Call(“Broadcast”, r, &res)
  19. front GSPOU GSPOU DUMS BHFOU BHFOU BHFOU rpc઀ଓ ϊʔυ(ϓϩηε)

  20. front • Ҋ݅ݻ༗ͷϩδοΫΛ୲౰ • ΄ͱΜͲ͕JSONΛड৴ͯ͠ɺctlr΁ϦΫΤετૹ৴ • Ҋ݅ݻ༗ͷϩδοΫͳͷͰ౎౓࣮૷͢Δ • DBؔ܎ͷॲཧ΋͜ͷϊʔυ͕ରԠ͢Δ

  21. controller GSPOU GSPOU DUMS BHFOU BHFOU BHFOU rpc઀ଓ ϊʔυ(ϓϩηε)

  22. controller • front͔ΒͷrpcϦΫΤετΛड͚෇͚Δϊʔυ • ෳ਺ͷΤʔδΣϯτΛ؅ཧ͢Δ • 1ϦΫΤετ಺ͷ௨஌਺͕ଟ͗͢Δ৔߹͸ෳ਺ ΤʔδΣϯτ΁෼ׂసૹ • ΤʔδΣϯτͷબผ͸ۭ͍͍ͯΔ΋ͷΛબͿ

    *
  23. ։͍͍ͯΔagentΛબ୒ // ϦΫΤετ༻νϟωϧΛ1ຊ͚ͩ༻ҙ req := make(chan *Request, bufSize) ! //

    ؅ཧ͢Δϊʔυ෼ɺϦΫΤετ༻νϟωϧ͔Βड৴͢ΔΰϧʔνϯΛىಈ͓ͯ͘͠ for agent := range agents { go func(c chan *Request){ _ = <-c }(req) } ! // νϟωϧʹϦΫΤετΛ౤͛Δͱ଴ػ͍ͯ͠ΔΰϧʔνϯͷͲΕ͔͕र͏ select { case req <- newReq: …. case <-time.After(timeoutInterval): …
  24. agent GSPOU GSPOU DUMS BHFOU BHFOU BHFOU rpc઀ଓ ϊʔυ(ϓϩηε)

  25. • ίϯτϩʔϥ͔ΒͷϦΫΤετΛ࣮ࡍʹ APNs/GCM΁ૹ৴͢Δ • ෳ਺ϦΫΤετ͸ՄೳͳΒ1ͭʹ·ͱΊΔ * agent

  26. ෳ਺·ͱΊͯૹ৴ que := make(chan *Message, bufSize) … // ctlr͔ΒͷϦΫΤετड৴ req

    := <-que msgs = append(msgs, req) for len(que) > 0 { msgs = append(msgs, <-que) } conn.WriteMessages(msgs)
  27. ੑೳଌఆ

  28. ੑೳଌఆ • ࣮ࡍͷAPNs/GCMΛ࢖ͬͯੑೳࢼݧ͸೉͍͠ • ࢼݧʹ଱͑͏Δྔͷ୺຤Λ͍࣋ͬͯͳ͍ • GCM͸1୺຤΁਺ສ݅ૹΔͱInternalServerError • Fake APNs/GCMΛ࡞ͬͯϕϯνϚʔΫ

    • গͳ͘ͱ΋લճΑΓྑ͘ͳͬͨͷ͔͸෼͔Δ
  29. ςετίʔυ // ςετ༻Fake APNsαʔό(ຊ෺͸gateway.push.apple.com:2195)Λىಈ s := apnstest.NewServer(func(w io.Writer, msg *apns.Message)

    { // wʹԿ͔Write͢Ε͹Τϥʔͱͯ͠ΫϥΠΞϯτʹฦ͢ // Կ΋͠ͳ͚Ε͹ਖ਼ৗʹ௨஌׬ྃ }) cli := NewClient(s.Addr) msg := newMessage() ! que := make([]<-chan error, b.N) for i := 0; i < b.N; i++ { que[i] = cli.Go(msg) }
  30. result. • ฒྻ਺ʹΑΔ͕10ʙ 30ඵͰεέʔϧ͢Δ Α͏ʹͳͬͨ • άϥϑ͸15ฒྻఔ౓ • 2ʙ300ສ͋ͨΓͳΒ ͓ͦΒ͘ಉ͡ఔ౓

    ඵ ඵ ඵ ඵ ඵ ສ ສ ສ ສ 1)1൛ (P൛
  31. डୗ։ൃͱGo

  32. • डୗ։ൃͷ৔߹ɺGoಋೖ͸೉͘͠Έ͑Δ • ٕज़ऀ਺͕গͳ͍ • ن໛ͷେ͖ͳ։ൃʹ଱͑ΒΕͳ͍ • 2೥ޙ3೥ޙ΋αϙʔτ͞Ε͍ͯΔ͔ෆಁ໌ • ࣮੷͕গͳ͍

    Goͬͯେৎ෉ʁ
  33. • ؀ڥߏங͕؆୯ • όΠφϦ͚ͩͰಈ࡞͢Δ
 ˠຊ൪؀ڥͰϥΠϒϥϦ؅ཧ͕ෆཁ • WindowsͰ΋LinuxͰ΋ಈ࡞͢Δ • ࠓ೥ྲྀߦΔݴޠʹϊϛωʔτ •

    ྲྀߦͬͨࠒʹࣗຫͰ͖Δɺ͔΋ʁ ͚ͩͲϝϦοτ΋
  34. GoͰྑ͔ͬͨ͜ͱ͸͋ͬͯ΋ Go͔ͩΒࠔͬͨ͜ͱ͸ແ͍ डୗͰ΋GoΛྲྀߦΒ͍ͤͯ͜͏

  35. ͋Γ͕ͱ͏͍͟͝·ͨ͠