900万ダウンロードアプリ『Gunosy』を支える大規模モバイルプッシュ通知基盤

 900万ダウンロードアプリ『Gunosy』を支える大規模モバイルプッシュ通知基盤

2015年6月3日に行われたAWS Summit Tokyo 2015 DevCon (http://www.awssummit.tokyo/) での発表スライドです。

Gunosy は「情報キュレーションアプリ」としてAmazon SNS を通じて1日に数多くのプッシュ通知を行っており、今やプッシュ通知は 900 万ダウンロードを超えた Gunosy にとって DAU を支える大きな要素となっています。本セッションではなぜ Amazon SNS を採用したのか、Gunosy でどのように AWS 上に大規模なプッシュ通知の仕組みを構築・運用しているのかをお話しいたします。

5919537a0ecfa5d4dea704cf878ae90e?s=128

toshimaru

June 03, 2015
Tweet

Transcript

  1. 900ສμ΢ϯϩʔυΞϓϦ ʰGunosyʱΛࢧ͑Δ େن໛ϞόΠϧϓογϡ௨஌ج൫ 2015.6.3(AWS(Summit(Tokyo(2015(DevCon 1

  2. ࣗݾ঺հ • ӿຊ"හؙ"(@toshimaru_e) • WEBΤϯδχΞˏGunosy • GunosyͰ͸Railsॻ͍ͯ·͢ • ޷͖ͳAWS"Service:"OpsWorks 2

  3. ΞδΣϯμ • ୈҰ෦"Gunosyͷϓογϡج൫ • ୈೋ෦"GunosyͰͷAmazon"SNSར༻ࣄྫ 3

  4. Gunosy • χϡʔεΞϓϦʢiPhone/Andoidʣ • 900ສμ΢ϯϩʔυ • ʮ৘ใΛੈքதͷਓʹ࠷దʹಧ͚Δʯ • ʲએ఻ʳઌ೔-gunosy.com-ΛେܕϦ χϡʔΞϧ

    4
  5. Gunosyͱϓογϡ௨஌'! • ϞόΠϧϓογϡ௨஌͸DAUΛࢧ͑Δॏཁཁૉ • ϓογϡ௨஌͸GunosyΞϓϦΛ։͖͔͚ͬ͘Λ༩͑Δ+→+Ϣʔ βʔɾϦςϯγϣϯ • ϓογϡ௨஌݁Ռ͕DAUΛࠨӈ͢Δ 5

  6. ̎ͭͷϓογϡ௨஌ 1. ఆ࣌ϓογϡ • ேɾனɾ༦ɾ໷ͷܾ·ͬͨ࣌ؒͷϓογϡ௨஌ 2. ଎ใϓογϡ • ଎ใੑͷ͋Δଈ࣌ૹΓ͍ͨϓογϡ௨஌ •

    ྫ:&େ͖ͳ஍਒ɺେ͖ͳࣄ݅ 6
  7. ఆ࣌ϓογϡ!! • ʲ͍ͭ❓ʳ"Ϣʔβʔ͕ઃఆͨ࣌ؒ͠ʹʢேɾனɾ༦ɾ໷ͷ̐ε ϩοτʣɺ • ʲ୭ʹ❓ʳʢϓογϡ௨஌ઃఆࡁΈͷʣϢʔβʔʹɺ • ʲͲΕ͘Β͍Ͱ❓ʳ"ʢAPIαʔόʔʹෛՙΛ͔͚ͳ͍ఔ౓Ͱʣ Ͱ͖Δ͚ͩ୹࣌ؒͰɺ •

    ʲԿΛ❓ʳ"ద੾ͳλΠτϧɾ಺༰Ͱϓογϡ௨஌ΛૹΔ 7
  8. ଎ใϓογϡ!! • ʲ͍ͭ❓ʳ"େ͖ͳࣄ݅ɾࣄނ͕ىͬͨ͜ॠؒʹɺ • ʲ୭ʹ❓ʳʢϓογϡ௨஌ઃఆࡁΈͷʣϢʔβʔʹɺ • ʲͲΕ͘Β͍Ͱ❓ʳ"Ͱ͖Δ͚ͩ୹࣌ؒͰɺ • ʲԿΛ❓ʳ"ద੾ͳλΠτϧɾ಺༰Ͱϓογϡ௨஌ΛૹΔ 8

  9. Gunosyϓογϡ௨஌ͷྺ࢙ͱมભ • ୈҰظ"~ϩʔΧϧϓογϡ࣌୅~ • ୈೋظ"~ϦϞʔτϓογϡҠߦظ~ • ୈࡾظ"~ຊ֨ϦϞʔτϓογϡ࣌୅~ • ୈ࢛ظ"~ύʔιφϥΠζυϓογϡ࣌୅~ 9

  10. ϓογϡୈҰظ ~ϩʔΧϧϓογϡ࣌୅~ • ϩʔΧϧϓογϡ࣌୅ • ઃఆ͞Εͨ࣌ؒʹʮχϡʔε͕ಧ͖· ͨ͠ʯͱ͍͏ఆܕจͰͷ௨஌ • ΫϥΠΞϯτଆʢiOS/AndroidʣͰ࣮૷ 10

  11. ݁Ռ • ϩʔΧϧϓογϡ௨஌Λ͖͔͚ͬʹΞϓϦΛ্ཱͪ͛ΔϢʔ βʔ͕૿Ճ • ·ͣ·ͣͷ։෧཰ 11

  12. ϓογϡୈೋظ ~ϦϞʔτϓογϡҠߦظ ~ • Amazon(SNSʢϞόΠϧϓογϡϝο ηʔδϯάػೳʣͷಋೖ • ʰχϡʔε͕ߋ৽͞Ε·ͨ͠ʮχϡʔ ελΠτϧʯ΄͔ʱͱ͍͏௨஌ •

    ϩʔΧϧϓογϡ(➡(ϦϞʔτϓογϡ ΁ͷҠߦ 12
  13. ݁Ռ • ϓογϡ։෧཰Ξοϓ • ϓογϡ௨஌"➡"DAU޲্ 13

  14. ໰୊!⾠ ࡶͳϓογϡ௨஌ӡ༻ 14

  15. ໰୊ • ։ൃऀ͕αʔόʔʹSSHϩάΠϯͯ͠ϓογϡͷͨΊͷίϚϯ υΛଧͬͯϓογϡ௨஌...%㽊 • ϓογϡ௨஌؅ཧը໘͕ෆ҆ఆ...%! 15

  16. ϓογϡୈࡾظ ~ຊ֨ϦϞʔτϓογϡ࣌ ୅~ • Amazon(SNSΛ༻͍ͨϦϞʔτϓογϡ ௨஌ͷຊ֨ӡ༻࣌୅ • େن໛ϓογϡʹ଱͑͏ΔΞʔΩςΫ νϟΛ͖ͪΜͱθϩ͔Βߟ͑ͯ࠶ઃܭ 16

  17. ϓογϡΞʔΩςΫνϟ ʢఆ࣌ϓογϡͷ৔߹ʣ 17

  18. 18

  19. ఆ࣌ϓογϡ 1. ϞόΠϧΤϯυϙΠϯτऔಘ 2. RedisʹΤϯΩϡʔ 3. ϫʔΧʔ͕σΩϡʔ 4. SNSʹPublish 19

  20. • Ϛελʔαʔόʔ • ϞόΠϧΤϯυϙΠϯτऔಘɺΤϯΩϡʔ • Redis • ϞόΠϧΤϯυϙΠϯτΛετΞ • ϫʔΧʔ

    • ϞόΠϧΤϯυϙΠϯτΛσΩϡʔɺSNS)Publish 20
  21. 1Πϯελϯε͋ͨΓͷ ϓογϡੑೳ 400#Pushes#/#Sec 21

  22. 1Πϯελϯε͋ͨΓͷՁ֨ $0.02%/%hour%(t2micro) 22

  23. ࣌ؒଳͰ૿ݮ͢Δ Πϯελϯε! (powered!by! OpsWorks) 23

  24. ϓογϡΞʔΩςΫνϟ • RedisΛ༻͍ͨγϯϓϧͳPub/Sub • εέʔϥϒϧͳϓογϡϫʔΧʔ • λΠϜϕʔεͳΠϯελϯεͰ௿ίετӡ༻ 24

  25. ϓογϡΞʔΩςΫνϟ ʢ଎ใϓογϡͷ৔߹ʣ 25

  26. 26

  27. ଎ใϓογϡ 1. ϓογϡ؅ཧը໘ʢRailsʣͰϓογϡΛઃఆ 2. ϞόΠϧΤϯυϙΠϯτऔಘ 3. RedisʹΤϯΩϡʔ 4. ϓογϡϫʔΧʔ͕σΩϡʔ 5.

    SNSʹPublish 27
  28. • Rails • ϞόΠϧΤϯυϙΠϯτऔಘɺΤϯΩϡʔ • Redis • ϞόΠϧΤϯυϙΠϯτΛετΞ • ϓογϡϫʔΧʔ

    • ϞόΠϧΤϯυϙΠϯτΛσΩϡʔɺSNS+Publish 28
  29. ϓογϡ؅ཧը໘ • ϓογϡ಺༰ɾλΠτϧΛઃఆ͢Δ؅ཧը໘ • Rails'ʴ'Sidekiq • SidekiqϫʔΧʔ͕ΤϯυϙΠϯτऔಘɺRedisʹΤϯΩϡʔ 29

  30. ໰୊!⾠ ϞόΠϧΤϯυϙΠϯτऔಘSQL ➡!͑ͬɺࢲͷΫΤϦ஗͗͢... 30

  31. ߴ଎Խରࡦ!⚡ endpoint(arnΛS3ϩʔυԽ 31

  32. 32

  33. ݁Ռ Android/iOS 10෼#➡#15ඵ 33

  34. ϓογϡୈ࢛ظ ~ύʔιφϥΠζυɾϓογϡ࣌୅~ • Ϣʔβʔͷᅂ޷ʹԠͨ͡ϓογϡ௨஌ • ઈࢍ։ൃத"! 34

  35. 35

  36. ৽ϓογϡΞʔΩςΫνϟ • Django(ͰϓογϡϦΫΤετड͚෇͚ • CeleryͰλεΫΩϡʔΠϯά • ૄ݁߹ͳϫʔΧʔ܈ 36

  37. To#be#con(nued 37

  38. ୈೋ෦ GunosyͰͷAmazon+SNSར༻ࣄྫ 38

  39. 39

  40. SNS༻ޠ • Device'Token:'ΞϓϦέʔγϣϯͷࣝผࢠɻ֤ϓϥοτϑΥʔϜ ͕ൃߦ • Endpoint'Arn:'Device'Token͔Βੜ੒͞ΕΔϞόΠϧͷΤϯυϙ Πϯτ.'SNSͰ͸͜ͷϞόΠϧϙΠϯτΛ࢖ͬͯϓογϡ͕ૹΒ ΕΔ 40

  41. Amazon'SNSͷϝϦοτ • APNS/GCMͷ֤ϓϥοτϑΥʔϜͷAPIΛந৅Խɺϓϥοτ ϑΥʔϜຖͷҧ͍Λҙࣝ͢Δඞཁ͕ͳ͍ 41

  42. Ձ֨ • 100ສϦΫΤετ/݄%͕ແྉ • ௒ա͢Δ৔߹%100ສϦΫΤετຖʹ%$0.5 42

  43. σόΠετʔΫϯͷ؅ཧͷ೉͠͞ 1. σόΠετʔΫϯ͕มΘΔ 2. Enable/Disable੍ޚ 3. DisableͳEndpoint3Arnͷ࡟আ 43

  44. σόΠετʔΫϯ͕มΘΔ(Android) Q.σόΠετʔΫϯͬͯͲΜͳͱ͖ʹมΘΔͷʁ 1. ΞϓϦΛ࠶Πϯετʔϧͨ͠ͱ͖ 2. ʮσʔλΛ࡟আʯ͞Εͨͱ͖ 3. ΞϓϦΛόʔδϣϯΞοϓͨ͠ͱ͖1 1"Ҿ༻ݩ:"ʲAndroidʳGCMͷregistra2onIdͷҰҙੑ"|"Monstar"Lab,"Inc. 44

  45. σόΠετʔΫϯ͕มΘΔ Q.͍ͭɺͳΜͰϦϑϨογϡ͢Δͷʁ A.#google༷ͷؾ෼࣍ୈɻɻɻ2 2"Ҿ༻ݩ:"ʲAndroidʳGCMͷregistra2onIdͷҰҙੑ"|"Monstar"Lab,"Inc. 45

  46. InstanceID Instance(ID(is(stable(but(may(become(invalid,(if: • App$deletes$Instance$ID • Device$is$factory$reset • User$uninstalls$the$app • User$clears$app$data0

    0"InstanceID"""|"""Google"APIs"for"Android"""|"""Google"Developers 46
  47. ϙΠϯτ!✔ • σόΠετʔΫϯΛఆظతʹߋ৽ • ߋ৽͞ΕͨσόΠετʔΫϯΛݩʹόονଆͰ࠶౓ϞόΠϧΤ ϯυϙΠϯτੜ੒ 47

  48. Enable/Disable੍ޚ CreatePla(ormEndpoint0͸0Pla(ormEndpoint0͕طʹଘࡏ͢Δ৔ ߹ɺ੒ޭ͠·͕͢0Enabled0ʹ͠·ͤΜɻͦͷͨΊɺ݁ՌΛฦ͢લ ʹ0Pla(ormEndpoint0͕0Enabled0ʹͳ͍ͬͯΔ͔Ͳ͏͔νΣοΫ͢ Δඞཁ͕͋Γ·͢ɻ3 3"Ҿ༻ݩ:"Amazon"SNS"ͷϞόΠϧτʔΫϯ؅ཧʹ͍ͭͯͷϕετϓϥΫςΟε"ʛ"Developers.IO 48

  49. SNSͰ͸ɺԿ౓͔௨஌ʹࣦഊͨ͠৔߹ɺendpoint͕disableʹͳΔ ※Ұ౓disableʹͳͬͯ͠·ͬͨendpoint͸ɺҎ߱ͲΕ͚ͩpublish ͯ͠΋APNS͕ୟ͔ΕΔ͜ͱ͸ͳ͍4 4"Ҿ༻ݩ:"iOS8ΞοϓσʔτͰΞϓϦ΁ͷϓογϡ௨஌ͰϋϚΔ఺"("Qiita 49

  50. ৸ͯΔEndpointArnΛى͜͢(Re-enableॲཧ) def reenable_endpoints(endpoint_arn) # client = AWS::SNS.new ###লུ### attributes =

    client.get_endpoint_attributes(endpoint_arn: endpoint_arn)[:attributes] if attributes['Enabled'] == 'false' # re-enable endpoint client.set_endpoint_attributes(endpoint_arn: endpoint_arn, attributes: {'Enabled' => 'true'}) end end 50
  51. DisableͳEndpoint.Arnͷ࡟আ • ϞόΠϧΤϯυϙΠϯτͷϜμͳPublish͸ͨ͘͠ͳ͍ • SNS΁ͷPublish࣌ʹdisableͳEndpointArn͸࡟আ 51

  52. !!SNS!ϕετɾϓϥΫςΟε!! • σόΠεຖ(iPhone/Android)ʹσόΠετʔΫϯΛ؅ཧ • ఆظతʹσόΠετʔΫϯΛνΣοΫͯ͠ߋ৽ • ϞόΠϧΤϯυϙΠϯτͷRe/enableॲཧ • disableͳEndpointArn͸࡟আͯ͠ϜμͳPublish͸߇͑Δ 52

  53. ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ We're%hiring!! 53

  54. ࢀߟ৘ใ • ʲAndroidʳGCMͷregistra0onIdͷҰҙੑ2|2Monstar2Lab,2Inc. • Amazon2SNS2ͷϞόΠϧτʔΫϯ؅ཧʹ͍ͭͯͷϕετϓϥΫ ςΟε2ʛ2Developers.IO • ؾܰͳSNS2Mobile2Push2ͷ࿩ • iOS8ΞοϓσʔτͰΞϓϦ΁ͷϓογϡ௨஌ͰϋϚΔ఺2F2Qiita

    54