$30 off During Our Annual Pro Sale. View Details »

アメブロ: Isomprhicアプリケーションのパフォーマンス・チューニング

HOU Bin
September 08, 2017

アメブロ: Isomprhicアプリケーションのパフォーマンス・チューニング

Frontrend Vol.10 - 夏の終わりに納涼パフォーマンス話
https://frontrend.connpass.com/event/63971/
https://freshlive.tv/tech-conference/151511

アメブロ: Isomprhicアプリケーションのパフォーマンス・チューニング

株式会社サイバーエージェント
アメーバブログ
侯斌 ( @houbin217jz )

アメブロSP面で去年刷新から今まで行われたパフォーマンス・チューニングについて紹介致します。特にサーバーとクライエントのキャッシュ設計とチューニング、コード分割、Service Workerのことを詳しくお伝えします。

参考資料:

アメブロ2017: Isomorphic Web Appの進化編
https://developers.cyberagent.co.jp/blog/archives/9001/

アメブロ2017 – 大規模サービスhttps化 ~ All Greenを目指して ~
https://developers.cyberagent.co.jp/blog/archives/7743/

開発、リリース、運用のサイクルを回す――アメブロのフロントエンドにおけるモダンなDevOps環境作り
http://www.atmarkit.co.jp/ait/articles/1704/13/news017.html

React/Redux/Node.jsのSSR/SPAを速くする6つのチューニングポイント
http://www.atmarkit.co.jp/ait/articles/1706/08/news011.html

アメブロでReactやIsomorphic Web Applicationを採用した理由――その成果と構成技術
http://www.atmarkit.co.jp/ait/articles/1702/09/news011.html

No more ガタンッ――React/Redux、Atomic Design、CSS Modulesを取り入れたアメブロのフロントエンド開発の裏側
http://www.atmarkit.co.jp/ait/articles/1702/28/news017.html

アメブロ2016 ~ React/ReduxでつくるIsomorphic web app ~
https://developers.cyberagent.co.jp/blog/archives/636/

アメブロ2016 ~ Isomorphic JavaScriptの詳しい話
https://developers.cyberagent.co.jp/blog/archives/3513/

HOU Bin

September 08, 2017
Tweet

More Decks by HOU Bin

Other Decks in Programming

Transcript

  1. ISOMORPHIC APPLICATIONͷ
    ύϑΥʔϚϯεɾνϡʔχϯά
    Ξϝϒϩ
    ި ඾ @ CYBERAGENT

    View Slide

  2. ࣗݾ঺հ
    ިɹ඾ʢί΢ɹώϯʣɹ 32࠽
    ▸ ത࢜ʢ޻ֶʣ
    ▸ ग़਎ɿதࠃɾྒྷೡʢ౦๺஍ํʣ
    ▸ גࣜձࣾαΠόʔΤʔδΣϯτ

    Ξϝʔόϒϩά ϑϩϯτϦχϡʔΞϧͷج൫ɾӡ༻Λ୲౰
    ▸ 2014೥4݄ɹגࣜձࣾαΠόʔΤʔδΣϯτɹ৽ଔೖࣾ

    2014೥5݄ɹϓϥοτϑΥʔϜɹαʔόʔΤϯδχΞʢJavaʣ

    2015೥4݄ɹ৽نϓϩδΣΫτɹαʔόʔΤϯδχΞʢGoʣ

    2015೥9݄ɹAmeba Ownd ɹɹ ϑϩϯτΤϯδχΞʢAngularJSʣ

    2016೥1݄ɹΞϝʔόϒϩάɹɹϑϩϯτΤϯδχΞʢReact + Node.jsʣɹ
    ▸ https://twitter.com/houbin217jz
    ▸ https://github.com/kouhin

    View Slide

  3. ΞϝʔόϒϩάɾSPϦχϡʔΞϧ
    ▸ 2016೥8݄ϦϦʔε
    ▸ ಺༰ɿ
    ▸ Javaϕʔε

    →ɹNode.js
    ▸ Server side renderingʢSSRʣ

    →ɹIsomorphic App (SSR + SPA)

    React + Redux + React Router
    ▸ σβΠϯϦχϡʔΞϧ
    ▸ ӡ༻ͳͲʢhttp://www.atmarkit.co.jp/
    ait/articles/1704/13/news017.htmlʣ
    ΞϝʔόϒϩάɾSPϦχϡʔΞϧ
    https://developers.cyberagent.co.jp/blog/archives/636/

    View Slide

  4. ΞϝʔόϒϩάɾSPϦχϡʔΞϧ
    ISOMORPHIC APPLICATIONύʔϑΥʔϚϯεɾνϡʔχϯά
    ▸ όοΫΤϯυͷΩϟογϡ
    ▸ ஗Ԇϩʔυ & ίʔυ෼ׂ
    ▸ Service Worker & ΞηοτͷϓϦΩϟογϡ)

    View Slide

  5. όοΫΤϯυ
    ͷΩϟογϡʂ

    View Slide

  6. όοΫΤϯυͷΩϟογϡ
    ͳͥόοΫΤϯυͷΩϟογϡ͕ॏཁͳͷ͔ - 1
    ▸ SSRͷύϑΥʔϚϯε͕ྑ͘ͳ͍ʂ
    ▸ ݪҼɿैདྷSPA޲͚ͷٕज़ΛαʔόʔͰ࣮ݱ

    ϨϯμϦϯάॲཧ͕ෳࡶ

    Perf (SSR React) < Perf (Template, e.g. Handlebars.js)

    View Slide

  7. ϨϯμϦϯάॲ
    ཧ͕ෳࡶͰɺαʔ
    όʔʹͱͬͯύ
    ϑΥʔϚϯε͕
    ѱ͍

    View Slide

  8. όοΫΤϯυͷΩϟογϡ
    ͳͥΩϟογϡ͕ॏཁͳͷ͔ - 2
    ▸ αʔόʔͷύϑΥʔϚϯε͸ಛʹॏཁ
    ▸ ཧ༝: ͢΂ͯͷϢʔβʔʹαʔϏεΛఏڙ
    SPA͕ಈ͔ͳͯ͘΋

    - Өڹൣғ͸֘౰ϢʔβʔͷΈ

    - ैདྷͷSSRͱ΄΅ಉ͘͡ӾཡͰ
    ͖Δɻ

    View Slide

  9. όοΫΤϯυͷΩϟογϡ
    ͳͥΩϟογϡ͕ॏཁͳͷ͔ - 3
    ▸ Ωϟογϡ͕ޮ͖΍͍͢
    ▸ ཧ༝: SEOΛॏࢹ͢ΔӾཡܥͷγεςϜ
    ί΢͘Μɺί΢͘ΜɺISOMORPHICͷ͜ͱΛฉ͖͍ͨͰ͚͢Ͳ
    ͲΜͳγεςϜͰ͔͢
    ͏ͪͷ؅ཧγεςϜͰ͢
    ͑ͬͬʁʁͲ͏ͯ͠ISOMORPHICͳͷʁ
    ΧοίΠΠ͔Β
    ͦΕ͸ISOMORPHICΛ΍Ίͨ΄͏͕͍͍

    View Slide

  10. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ ໰୊఺Λચ͍ग़͢
    ▸ ԿΛΩϟογϡ͢Δ
    ▸ Ωϟογϡอଘ͢ΔλΠϛϯά
    ▸ Ωϟογϡ࡟আ͢ΔλΠϛϯά
    ▸ Local Cache VS Cache Server

    View Slide

  11. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ ΞϝϒϩSSRͷྲྀΕ
    ▸ PathϚονϯάɺίϯϙωϯ
    τͱඞཁͳॲཧΛऔΓग़͢
    ▸ Redux Store४උ: APIίʔϧ
    ΛؚΊɺඞཁͳσʔλॲཧ
    Λߦ͏‼
    ▸ Redux Store +
    ReactDOMServer.renderTo
    String()‼ = HTML
    ▸ Q1. ԿΛΩϟογϡ͢Δ



    ߋ৽ස౓͕௿͍Object



    ReactDOMServer

    .renderToString() ͷ݁Ռ

    View Slide

  12. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ ԿΛΩϟογϡ͢Δ: ReactDOMServer.renderToString()
    ▸ ΫϥΠΤϯτʹΑͬͯಈతʹมΘΔ಺༰͕͋ΔͷͰɺੜ੒͞ΕͨHTMLΛͦͷ·
    ·࢖͑ͳ͍
    ReactDOMServer.renderToString() Template
    Create Template
    Template
    +
    Client Info (e.g. user-agent)
    =
    HTML
    Cache

    View Slide

  13. όοΫΤϯυͷΩϟογϡ
    ͪͳΈʹ
    ▸ ΞϝϒϩͰ͸Ұ൪࠷ॳʹHTML(ReactDOMServer

    .renderToString) ͷΩϟογϡΛͪΌΜͱ࣮૷͕ͨ͠ɺAPI/
    ObjectͷΩϟογϡʹ͍ͭͯ͋·Γॏࢹ͠ͳ͔ͬͨɻ
    ▸ 6݄ͷτϐοΫεͷ͖͔͚ͬͰAPI/ObjectΛਫ਼ࠪ͠ɺΩϟο
    γϡΛ͖ͪΜͱ࣮૷ͯ͠ɺ͔ͳΓྑ͍݁Ռ͕ग़ͨɻ

    View Slide

  14. όοΫΤϯυͷΩϟογϡ
    ໷ϐʔΫଳͷฏۉϨεϙϯελΠϜ
    Before: 26ms
    After: 17ms
    API/Object Cache࣮૷લޙͷൺֱ

    View Slide

  15. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Q2. ΩϟογϡอଘλΠϛϯά
    ▸ ΞΫηε͢Δͱ͖ʹɺΩϟογϡ͕ݟ͔ͭΒͳ͔ͬͨΒɺ
    ॲཧͯ͠Ωϟογϡอଘ͢Δɻ

    View Slide

  16. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Q3. Ωϟογϡ࡟আλΠϛϯά
    ▸ هࣄΛߋ৽͞ΕͨΒɺهࣄIDΛ΋ΒͬͯهࣄͷΩϟο
    γϡΛ࡟আ͢Ε͹OK
    ͜Ε͸μϝʂʂ

    View Slide

  17. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Q3. Ωϟογϡ͔Β࡟আλΠϛϯά
    ▸ هࣄΛߋ৽͞ΕͨΒɺهࣄIDΛ΋ΒͬͯهࣄͷΩϟογϡΛ࡟আ͢Ε͹OK ʢ͜Ε͸μϝʂʣ
    ▸ هࣄͷߋ৽

    ˠɹهࣄϖʔδͷΩϟογϡΛ࡟আ
    ▸ هࣄͷ౤ߘ

    ˠɹهࣄҰཡͷΩϟογϡΛ࡟আ

    ˠɹهࣄৄࡉͷϦϯΫΛߋ৽͠ͳ͍ͱ͍͚ͳ͍ͷͰɺهࣄৄࡉͷΩϟογϡΛ࡟আ͢Δඞཁ͕͋Δ
    ▸ εΩϯɾϓϩϑΟʔϧͷߋ৽

    ˠɹϒϩΨʔͷશϖʔδͷΩϟγϡΛ࡟আ
    ࣮૷͸ෳࡶʹͳΔ͠ɺ

    ສ͕ҰΩϟογϡͷ࡟আ͕࿙ΕͨΒɺ͜Θ͍ʂʂʂʂʂ

    View Slide

  18. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Q3. Ωϟογϡ͔Β࡟আλΠϛϯά
    ▸ Namespace (Ameba ID)ຖΛ࡟আ

    ▸ Fallback: ΩϟογϡͷTTLΛઃఆ 

    ສ͕Ұ࡟আࣦഊͯ͠΋ɺTTLʹΑΓΩϟογϡΛࣦޮͤ͞Δ
    namespace: “staff”

    https://ameblo.jp/staff 

    https://ameblo.jp/staff/message-board.html

    https://ameblo.jp/staff/entry-12308025976.html

    https://ameblo.jp/staff/**
    DELETE /cache?amebaId=staff

    View Slide

  19. ▸ Q3. Ωϟογϡ͔Β࡟আλΠϛϯά
    ▸ τϥϯβΫγϣϯ໰୊
    όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ߋ৽
    user_a
    DELETE 

    /cache?

    ameba_id = user_a
    user_b API Server Node.js Server Cache
    Ӿཡ
    Rendering
    Evict Cache /ameba_id
    Save
    Ωϟογϡ࡟আ

    ࣦഊʂ

    View Slide

  20. ▸ Q3. Ωϟογϡ͔Β࡟আλΠϛϯά
    ▸ τϥϯβΫγϣϯ໰୊ʢόʔδϣϯ෇͖ʣ
    όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ߋ৽
    user_a
    DELETE 

    /cache?

    ameba_id = user_a
    user_b API Server Node.js Server Cache
    Ӿཡ
    Rendering
    Update user_a/version: 4
    Save to /user_a/3/
    GET user_a/version: 3

    View Slide

  21. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Q4. Local Cache VS Cache Server
    ▸ Node.jsͷΠϯελϯε਺͕ଟ͍
    ▸ αʔϏε಺ʹॏෳϨϯμϦϯάͨ͘͠ͳ͍͔Β

    Ұ൪࠷ॳʹϦΫΤετΛड͚औͬͨαʔόʔ͕Ωϟογϡ͞Εͨ΋ͷΛଞͷαʔ
    όʔʹڞ༗Ͱ͖Δ → Cache Server͕ඞཁ
    ▸ On-memory͸ૣ͍Ͱ͔͢ΒɺΑ͘࢖ΘΕΔ΋ͷΛOn-memoryʹ΋อଘ͢Δ
    (LRU-cache) → Local Cache͕ඞཁ
    ▸ 2֊૚: On-memory Cache (LRU-cache) + Cache Server

    View Slide

  22. όοΫΤϯυͷΩϟογϡ
    ΞϝϒϩͷόοΫΤϯυΩϟογϡͷઃܭ
    ▸ Ωϟογϡͷઃܭͷ·ͱΊ
    ▸ HTMLςϯϓϨʔτ + APIͷσʔλΩϟογϡ
    ▸ Namespace (AmebaId + Version) ͰΩϟογϡอଘɾΞ
    ΫςΟϒతͳ࡟আ(Versionߋ৽)
    ▸ On-memory cache + Cache Server 2֊૚

    View Slide

  23. όοΫΤϯυͷΩϟογϡ
    Ξϝϒϩ όοΫΤϯυΩϟογϡͷશମਤ

    View Slide

  24. όοΫΤϯυͷΩϟογϡ
    ݁Ռ1: NEW RELICͰهࣄৄࡉͷΩϟογϡঢ়گ
    Cache Hit!

    View Slide

  25. όοΫΤϯυͷΩϟογϡ
    ݁Ռ2: NEW RELICͰهࣄҰཡͷΩϟογϡঢ়گ
    Cache Hit!

    View Slide

  26. όοΫΤϯυͷΩϟογϡ
    ݁Ռ3: DATADOGͷMEMCACHED HIT RATE

    View Slide

  27. ஗Ԇϩʔυ
    LAZY LOAD

    View Slide

  28. ஗Ԇϩʔυ
    ஗Ԇϩʔυ
    ▸ ద੾ͳλΠϛϯάͰద੾ͳॲཧΛߦ͏
    ▸ SSR → SPA
    ▸ ϖʔδͷ্ → ϖʔδͷԼ
    ▸ ίʔυͷ஗ԆධՁ: ίʔυ෼ׂ

    View Slide

  29. ஗Ԇϩʔυ
    ஗Ԇϩʔυ: SSR → SPA
    ▸ SSRͷྲྀΕ
    ▸ PathϚονϯάɺίϯϙωϯ
    τͱඞཁͳॲཧΛऔΓग़͢
    ▸ Redux Store४උ: APIίʔϧ
    ΛؚΊɺඞཁͳσʔλॲཧ
    Λߦ͏
    ▸ Redux Store +
    ReactDOMServer.renderTo
    String() = HTML
    https://github.com/kouhin/react-router-hook
    https://github.com/kouhin/rrr-lazy

    View Slide

  30. ஗Ԇϩʔυ
    ஗Ԇϩʔυ: ϖʔδͷ্ → ϖʔδͷԼ

    View Slide

  31. ஗Ԇϩʔυ
    ͔ͤͬ͘αʔόʔ͔ΒϑϩϯτʹདྷͨͷͰɺ

    CHROME DEV TOOLͰύϑΥʔϚϯεΛΈͯΈΑ͏ʂ
    ϖʔδʹؔ܎ͳ͍Ϟ
    δϡʔϧ΋ϩʔυ͠
    ͯ͠·ͬͯɺJSධՁ
    ͕࣌ؒ௕͘ͳͬͨ

    View Slide

  32. ίʔυ෼ׂ
    ίʔυ෼ׂͷϝϦοτ
    ▸ ඞཁ͸ͳ͍ίϯϙωϯτΛϩʔυ͠ͳ͍Α͏ʹ
    ▸ JSධՁ͕࣌ؒ୹͘ͳΔ
    ▸ main.js๲େԽΛ๷͙
    ▸ ৽͍͠ػೳΛͲΜͲΜ௥Ճͯ͠OK

    View Slide

  33. ίʔυ෼ׂ
    ίʔυ෼ׂͷํ๏
    ▸ Webpack
    ▸ ෼ׂཻ౓ɿAtomicσβΠϯ ͷ Organismsຖ
    ▸ ෼ׂ͞ΕͨBundleͷαΠζΛݮΒ͢ϓϥάΠϯ
    ▸ ModuleConcatenationPlugin
    ▸ AggressiveMergingPlugin

    View Slide

  34. ίʔυ෼ׂ
    ίʔυ෼ׂͷํ๏ɿWEBPACK
    ▸ https://webpack.js.org/guides/code-splitting
    ▸ require.ensure, bundle loader, Dynamic imports()
    ▸ ΞϝϒϩɿDynamic imports()

    Lazy Loadʹ͍ͨ͠৔߹: 

    const loadExample = () => import(‘./ExampleComponent’)

    View Slide

  35. ίʔυ෼ׂ
    ίʔυ෼ׂͷํ๏ɿཻ౓
    ▸ AtomicσβΠϯ: Organismsຖ
    هࣄҰཡTemplate
    AtomicσβΠϯ

    View Slide

  36. ίʔυ෼ׂ
    ίʔυ෼ׂͷํ๏ɿཻ౓
    ▸ AtomσβΠϯ: Organisms୯Ґ
    هࣄҰཡTemplate
    rrr--lazy΋Dynamic Import()ʹରԠࡁΈ

    View Slide

  37. ίʔυ෼ׂ
    ݁Ռ1ɿ࣮ࡍͷಈ͖

    View Slide

  38. ίʔυ෼ׂ
    ݁Ռ2ɿJSධՁ࣌ؒ

    View Slide

  39. ίʔυ෼ׂ
    ίʔυ෼ׂͷҰ൪େ͖͍σϝϦοτ
    ▸ ݱ࣌఺ͰWebpackͷ࠶Ϗϧυ଎౓͕͔ͳΓ஗͍ʂ
    ▸ ϩʔΧϧͷ։ൃϞʔυͰίʔυΛमਖ਼ͨ͠Βɺ10s - 20s
    ͔͔Δ
    ▸ ղܾํ๏ɿϩʔΧϧͰίʔυ෼ׂΛແޮʹ͢Δ
    ▸ babel-plugin-dynamic-import-webpack

    babel-plugin-remove-webpack


    View Slide

  40. ίʔυ෼ׂͯ͠΋ɺΞηοτ
    ͷαΠζ͸΍͸Γେ͖͍ʂʂ

    View Slide

  41. SERVICE WORKER & ΞηοτͷϓϦΩϟογϡ)
    SERVICE WORKER
    ▸ લఏɿHTTPSʂ
    ▸ Ξϝϒϩ2017 – େن໛αʔϏεhttpsԽ ~ All GreenΛ໨
    ࢦͯ͠ ~

    https://developers.cyberagent.co.jp/blog/archives/7743

    View Slide

  42. SERVICE WORKER & ΞηοτͷϓϦΩϟογϡ)
    SERVICE WORKER
    ▸ service-worker.jsΠϯετʔϧλΠϛϯά
    ▸ AMPϖʔδʹΞΫηε
    ▸ ΞϝϒϩSPϖʔδʹΞΫηε

    View Slide

  43. SERVICE WORKER & ΞηοτͷϓϦΩϟογϡ)
    SERVICE WORKER - ΤϯτϦ
    ▸ AMPϖʔδɿඞཁͳΞηοτΛϓϦϩʔυɾΩϟογϡ


    Install-service-worker.html
    service-worker.js

    (installer)
    service-worker.js

    (CDN)
    ΫϩευϝΠϯ
    importScripts
    Assets

    View Slide

  44. SERVICE WORKER & ΞηοτͷϓϦΩϟογϡ)
    SERVICE WORKER - ΤϯτϦ
    ▸ ΞϝϒϩSPϖʔδɿΞηοτΛΩϟογϡ
    service-worker.js

    (installer)
    service-worker.js

    (CDN)
    ΫϩευϝΠϯ
    importScripts
    Assets

    View Slide

  45. SERVICE WORKER & ΞηοτͷϓϦΩϟογϡ)
    SERVICE WORKER - ࣮૷
    ▸ Webpack + Workbox


    https://github.com/GoogleChrome/workbox

    View Slide

  46. ݁Ռ͸ʁ

    View Slide

  47. View Slide

  48. কདྷͷల๬
    কདྷͷల๬
    ▸ React 16 & SSR
    ▸ HTTP/2 & ίʔυ෼ׂ
    ▸ PWA & Service Worker

    View Slide

  49. কདྷͷల๬
    REACT 16 & SSR
    ▸ Ұ൪ظ଴͍ͯ͠Δͷ͸SSRύϑΥʔϚϯεͷվળ
    React 15
    ϚΠϯεϨουΛϒϩο
    Ϋ͞ΕΔͷͰɺ
    ݱࡏϚϧνϓϩηεͰ
    ϨϯμϦϯά͍ͯ͠Δ

    View Slide

  50. কདྷͷల๬
    REACT 16
    ▸ Ұ൪ظ଴͍ͯ͠Δͷ͸SSRύϑΥʔϚϯεͷվળ
    React 16

    View Slide

  51. ▸ ݱঢ়ɿChromeͳͲ͸ಉ࣌ʹૹ৴͢ΔϦΫΤετ͸6ͭ·Ͱ
    ʹ੍ݶ͞Ε͍ͯΔ͔Βɺ෼ׂ͞ΕͨJSϑΝΠϧΛಉ࣌ʹϩʔ
    υ͢ΔࡍʹϒϩοΫ͞Εͯ͠·͏ɻ
    ▸ ࠓޙɿHTTP/2 ετϦʔϜͷଟॏԽΛར༻͠ɺύϑΥʔϚϯ
    ε޲্
    কདྷͷల๬
    HTTP/2 & ίʔυ෼ׂ

    View Slide

  52. কདྷͷల๬
    PWA & SERVICE WORKER
    ▸ ݱঢ়: Service Worker = ϓϦΩϟογϡ
    ▸ ࠓޙ
    ▸ Add to Home Screen
    ▸ App ShellϞσϧ
    ▸ ΦϑϥΠϯϞʔυ
    ▸ ௨஌

    View Slide

  53. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide