Go Conference 2014 spring で発表した資料。 受託開発に持ち込んだ事例紹介。 http://connpass.com/event/6370/
Goۦಈ։ൃͰPushΤϯδϯΛ࡞ͬͨ@plan9userGoCon 2014 spring
View Slide
GoΛ͍͍ͨҰ৺Ͱडୗۀ࣋ͪࠐΜͩ࣌ͷ
ࣗݾհ• ଟګฏ• झຯ”Plan 9”Ͱ͢ʂ• Go͖ͳΒPlan 9ͷࢥΉͣ• 2011͔ΒϑΣϯϦϧͰಇ͍ͯ·͢
• ͜ͳ͍ͩSleipnir 6͕ग़·ͨ͠ʂ• ڞಉ։ൃ෦• اۀ༷͔Βͷडୗ։ൃΛߦ͏෦ॺ• ࣮հ - http://biz.fenrir-inc.com• Sleipnirͷ͝ҙݟެࣜαΠτ͔ΒϑΣϯϦϧגࣜձࣾ
• εϚʔτϑΥϯΞϓϦ։ൃͬͯ·͢• iOS, Android• Windows 8 (एׯ)• ࡢ͋ͨΓ͔ΒXamarin͡Ί·ͨ͠ۀ༰
go?• ϓογϡ௨• ࠃαʔϏεͰͳ͚Ε×ɹͱ͔• ࣗͰશମΛίϯτϩʔϧ͍ͨ͠ɹͱ͔• ങ͍Γ͍ͨɹͱ͔
push௨ͷ͘͠Έ1. ΞϓϦτʔΫϯΛαʔόʹૹ৴2. αʔόอଘ͍ͯ͠ΔτʔΫϯͱϝοηʔδΛηοτʹͯ͠APNs/GCMૹ৴3. ϝοηʔδ͕֤ಧܾͯ͘͘͠͠ͳ͍Μ͚ͩͲ…
• ࠷ॳPHPͰ࣮• ਫ४Λຬͨͤͳ͍• ेສ௨ʹ͑ΒΕͳ͍• ઃܭ͕·͔ͣͬͨ• PHPѱ͘ͳ͍performance problems…ඵඵඵඵඵສ ສ ສ ສ
ͩΊͩͬͨͱ͜Ζ
problem?• PHPͳͷͰฒྻԽ͕͔ͬͨ͠• ೋॏૹ৴ࢭͷͨΊDBΛΩϡʔʹ͍ͯͨ͠• ௨৴ΤϥʔͰϦτϥΠ͖͢߹్தͰམͪͨ߹Λఆ• ྃϚʔΫDBʹ͍࣋ͬͯͨ
goal?• ॲཧͷͪ࣌ؒΛͳͯ͘͠ੑೳΛ্͛Δ• ͕ଟ͍ͱ͖ࢄͯ͠ૹ৴͢Δ• ෳϚγϯͰͻͱͭͷγεςϜʹ͢Δ• DBͷґଘΛͳ͘͢
͓ʁ
͜ΕGoͷग़൪͡ΌͶʁ
GoΛΉཧ༝(࣌)• Rob PikeRuss Cox͕ࢀՃͯ͠Δ• Plan 9ʹؔΘ͓ͬͯΒΕ·ͨ͠• Alef, Limbo͔Βଓ͘CSPྑ͍• ඪ४ύοέʔδॆ࣮ͯͦ͠͏(งғؾ)
GoͱXamarinಉ࣌ೖܾఆ• Α͘௨ͬͨͳͱࢥ͍·͢…• ӡ͕ྑ͘ظؒݶఆͷΞϓϦͩͬͨ• ظӡ༻ͳΒอकߟ͑Δඞཁ͕͋Δ• ։ൃظ͕ؒൺֱత͘औΕͨ• ࠷ॳௐͳ͕Βॻ͘ͷͰޮѱ͍
GoͰॻ͘ʂ
overviewGSPOUGSPOUDUMSBHFOUBHFOUBHFOUrpcଓϊʔυ(ϓϩηε)
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)
frontGSPOUGSPOUDUMSBHFOUBHFOUBHFOUrpcଓϊʔυ(ϓϩηε)
front• Ҋ݅ݻ༗ͷϩδοΫΛ୲• ΄ͱΜͲ͕JSONΛड৴ͯ͠ɺctlrϦΫΤετૹ৴• Ҋ݅ݻ༗ͷϩδοΫͳͷͰ࣮͢Δ• DBؔͷॲཧ͜ͷϊʔυ͕ରԠ͢Δ
controllerGSPOUGSPOUDUMSBHFOUBHFOUBHFOUrpcଓϊʔυ(ϓϩηε)
controller• front͔ΒͷrpcϦΫΤετΛड͚͚Δϊʔυ• ෳͷΤʔδΣϯτΛཧ͢Δ• 1ϦΫΤετͷ௨͕ଟ͗͢Δ߹ෳΤʔδΣϯτׂసૹ• ΤʔδΣϯτͷબผۭ͍͍ͯΔͷΛબͿ *
։͍͍ͯΔ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):…
agentGSPOUGSPOUDUMSBHFOUBHFOUBHFOUrpcଓϊʔυ(ϓϩηε)
• ίϯτϩʔϥ͔ΒͷϦΫΤετΛ࣮ࡍʹAPNs/GCMૹ৴͢Δ• ෳϦΫΤετՄೳͳΒ1ͭʹ·ͱΊΔ *agent
ෳ·ͱΊͯૹ৴que := make(chan *Message, bufSize)…// ctlr͔ΒͷϦΫΤετड৴req := <-quemsgs = append(msgs, req)for len(que) > 0 {msgs = append(msgs, <-que)}conn.WriteMessages(msgs)
ੑೳଌఆ
ੑೳଌఆ• ࣮ࡍͷAPNs/GCMΛͬͯੑೳࢼݧ͍͠• ࢼݧʹ͑͏ΔྔͷΛ͍࣋ͬͯͳ͍• GCM1ສ݅ૹΔͱInternalServerError• Fake APNs/GCMΛ࡞ͬͯϕϯνϚʔΫ• গͳ͘ͱલճΑΓྑ͘ͳͬͨͷ͔͔Δ
ςετίʔυ// ςετ༻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)}
result.• ฒྻʹΑΔ͕10ʙ30ඵͰεέʔϧ͢ΔΑ͏ʹͳͬͨ• άϥϑ15ฒྻఔ• 2ʙ300ສ͋ͨΓͳΒ͓ͦΒ͘ಉ͡ఔඵඵඵඵඵສ ສ ສ ສ1)1൛ (P൛
डୗ։ൃͱGo
• डୗ։ൃͷ߹ɺGoಋೖ͘͠Έ͑Δ• ٕज़ऀ͕গͳ͍• نͷେ͖ͳ։ൃʹ͑ΒΕͳ͍• 2ޙ3ޙαϙʔτ͞Ε͍ͯΔ͔ෆಁ໌• ࣮͕গͳ͍Goͬͯେৎʁ
• ڥߏங͕؆୯• όΠφϦ͚ͩͰಈ࡞͢Δ ˠຊ൪ڥͰϥΠϒϥϦཧ͕ෆཁ• WindowsͰLinuxͰಈ࡞͢Δ• ࠓྲྀߦΔݴޠʹϊϛωʔτ• ྲྀߦͬͨࠒʹࣗຫͰ͖Δɺ͔ʁ͚ͩͲϝϦοτ
GoͰྑ͔ͬͨ͜ͱ͋ͬͯGo͔ͩΒࠔͬͨ͜ͱແ͍डୗͰGoΛྲྀߦΒ͍ͤͯ͜͏
͋Γ͕ͱ͏͍͟͝·ͨ͠