Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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 上に大規模なプッシュ通知の仕組みを構築・運用しているのかをお話しいたします。

toshimaru

June 03, 2015
Tweet

More Decks by toshimaru

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  6. ̎ͭͷϓογϡ௨஌
    1. ఆ࣌ϓογϡ
    • ேɾனɾ༦ɾ໷ͷܾ·ͬͨ࣌ؒͷϓογϡ௨஌
    2. ଎ใϓογϡ
    • ଎ใੑͷ͋Δଈ࣌ૹΓ͍ͨϓογϡ௨஌
    • ྫ:&େ͖ͳ஍਒ɺେ͖ͳࣄ݅
    6

    View Slide

  7. ఆ࣌ϓογϡ!!
    • ʲ͍ͭ❓ʳ"Ϣʔβʔ͕ઃఆͨ࣌ؒ͠ʹʢேɾனɾ༦ɾ໷ͷ̐ε
    ϩοτʣɺ
    • ʲ୭ʹ❓ʳʢϓογϡ௨஌ઃఆࡁΈͷʣϢʔβʔʹɺ
    • ʲͲΕ͘Β͍Ͱ❓ʳ"ʢAPIαʔόʔʹෛՙΛ͔͚ͳ͍ఔ౓Ͱʣ
    Ͱ͖Δ͚ͩ୹࣌ؒͰɺ
    • ʲԿΛ❓ʳ"ద੾ͳλΠτϧɾ಺༰Ͱϓογϡ௨஌ΛૹΔ
    7

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. ݁Ռ
    • ϓογϡ։෧཰Ξοϓ
    • ϓογϡ௨஌"➡"DAU޲্
    13

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. 18

    View Slide

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

    View Slide

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

    View Slide

  21. 1Πϯελϯε͋ͨΓͷ
    ϓογϡੑೳ
    400#Pushes#/#Sec
    21

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. 26

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  32. 32

    View Slide

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

    View Slide

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

    View Slide

  35. 35

    View Slide

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

    View Slide

  37. To#be#con(nued
    37

    View Slide

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

    View Slide

  39. 39

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  47. ϙΠϯτ!✔
    • σόΠετʔΫϯΛఆظతʹߋ৽
    • ߋ৽͞ΕͨσόΠετʔΫϯΛݩʹόονଆͰ࠶౓ϞόΠϧΤ
    ϯυϙΠϯτੜ੒
    47

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  51. DisableͳEndpoint.Arnͷ࡟আ
    • ϞόΠϧΤϯυϙΠϯτͷϜμͳPublish͸ͨ͘͠ͳ͍
    • SNS΁ͷPublish࣌ʹdisableͳEndpointArn͸࡟আ
    51

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide