Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
スケール可能で運用しやすいWebSocketサーバ設計の課題と工夫 / The develop...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
mackee
August 23, 2018
20k
11
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
スケール可能で運用しやすいWebSocketサーバ設計の課題と工夫 / The development of scalable and operating friendly WebSocket Server
CEDEC 2018
mackee
August 23, 2018
More Decks by mackee
See All by mackee
Go1.27で導入されるジェネリクスメソッドでできること
mackee
0
830
perlをWebAssembly上で動かすと何が嬉しいの??? / Where does Perl-on-Wasm actually make sense?
mackee
0
1.4k
Agentに至る道 〜なぜLLMは自動でコードを書けるようになったのか〜
mackee
6
6.5k
今!ソフトウェアエンジニアがハードウェアに手を出すには
mackee
14
7.5k
ワンバイナリWebサービスのススメ
mackee
10
9.2k
tanukistack ライブコーディング / tanukistack live-coding
mackee
0
870
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
1.2k
perl for shell, awk and sed programmers
mackee
3
2.9k
今更GoのWebフレームワークを作ろうとしているワケ / Why am I trying to create a Go web framework now?
mackee
1
1.1k
Featured
See All Featured
RailsConf 2023
tenderlove
30
1.6k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
430
Unsuck your backbone
ammeep
672
58k
Odyssey Design
rkendrick25
PRO
2
810
Site-Speed That Sticks
csswizardry
13
1.5k
From π to Pie charts
rasagy
1
370
We Are The Robots
honzajavorek
0
380
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
760
A designer walks into a library…
pauljervisheath
211
25k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
530
How STYLIGHT went responsive
nonsquared
100
6.3k
Transcript
εέʔϧՄೳͰ ӡ༻͍͢͠ WebSocketαʔόઃܭͷ ՝ͱ CEDEC 2018 ໘ന๏ਓΧϠοΫɹ୩ ਅۏ
͜ͷηογϣϯͰ͢͜ͱ • ैདྷͷWebΞϓϦέʔγϣϯͷ࡞ΓํͷԆઢ্Ͱ • ϛυϧΣΞΛ͚Ճ͑ΔܗͰWebSocketʹΑΔϦΞϧ λΠϜ௨৴Λ༻͍Δ • ήʔϜαʔόΛ։ൃɾӡ༻ͯ͠Έͨ ͦͷ࣌ͷͱۤ࿑Λ͠·͢ɻ
͜ͷηογϣϯͰ͞ΕΔ͜ͱ ౦ژϓϦζϯ1ͱ͍͏ϞόΠϧήʔϜͷࣄྫͰ͢ 1 https://tokyo-prison.kayac.com/
ήʔϜͷಛੑ • λʔϯ੍ɻλʔϯҰఆඵ͕ܦա͢Δͱऴྃ͢Δɻλʔϯ ͋Δఔࣗ༝ʹಈ͚Δ
ήʔϜͷಛੑ • ϓϨΠϠʔ3ਓ vs ϓϨΠϠʔ3ਓ
ߨԋऀͷόοΫάϥϯυ • ໘ന๏ਓΧϠοΫ ιʔγϟϧήʔϜࣄۀ෦ • αʔόαΠυΛઐͰ୲ɻΞϓϦέʔγϣϯίʔυΛॻ͕͘ ΠϯϑϥߏஙΓɺӡ༻Δ • झຯPerlͱ3DϓϦϯλվͱϛυϧΣΞ։ൃ
ैདྷͷWebΞϓϦͰ ΞʔΩςΫνϟͰ WebSocketΛ༻͍Δͱ͖ͷ՝
આ໌ͷॱ൪ 1. ैདྷͷWebΞϓϦͷߏ 2. WebSocketΛ࢝Ίͱͨ͠ੜଘ࣌ؒͷ͍ηογϣϯΛѻ͏্Ͱ ͷ 3. ղܾํ๏(kuiperbeltͷհ)
͜͜Ͱ͍͏WebΞϓϦͱ • ΠϯλʔωοτΛ௨ͬͯओʹHTTPΛ͏ ΞϓϦέʔγϣϯ • HTTP·ͣϦΫΤετ͋Γ͖
ͳͥHTTPΛ͏ͷ͔ • ͍͍ͩͨͷWebϑϨʔϜϫʔΫHTTPΛѻ͏ͨΊʹ࡞ΒΕ͍ͯ Δ • curlΛ͡Ίͱͨ͠HTTPΛσόοά͢ΔͨΊͷπʔϧݟ͕ ੈͷதʹ͋;Ε͍ͯΔ • HTTPεςʔτϨε͕લఏͷϓϩτίϧͳͷͰεέʔϧͤ͞Δ ͷʹ༗ར(ޙड़)
εςʔτϨε͔ͩΒԣʹ૿ͤΔ Keep-AliveͰTCPଓ͍ճ͠Λߦ͏߹͋Δ͕ɺHTTPͷ͔ΒݟΕಉ͡
εςʔτϨε͔ͩΒԣʹ૿ͤΔ
Ϣʔβಉ࣌ʹϦΫΤετΛड͚͍ͯΔ͜ ͱͳ͍
WebΞϓϦέʔγϣϯͷੈք • HTTP͕εςʔτϨεͳͷͰԣʹಉ͡ΞϓϦΛฒͯLBʹೖΕ Δ • ෛՙࢄͱHAత • Lightweight Language(PHPRuby2ͳͲ)͕ΘΕΔ͜ͱ͕͋Δ •
͜ΕΒϚϧνϓϩηεϞσϧ͕ओྲྀ 2 ͪΖΜJavaC#ͰΉͱ͜Ζ͋ΓɺͦΕΒϚϧνεϨου
ϦΞϧλΠϜ௨৴ΛWebͷԆͰΔબࢶ • Long Polling • WebSocket • WebRTC DataChannel •
͋Δ͍ੜιέοτ
ͳͥWebSocketΛ͏ͷ͔ => ͍ͷʹר͔Εͨ΄͏ָ͕͕Ͱ͖Δ • 2011ʹඪ४ࡦఆ͞Ε͔ͯΒ͕࣌ؒܦͪϥΠϒϥϦ͕ރΕ͍ͯ Δ • ੜιέοτͱҧͬͯϥΠϒϥϦΛࣗͰॻ͔ͳͯ͘Α͍ • wscatΛ࢝Ίͱͨ͠σόοάπʔϧ๛
• TCPͳͷͰ࠶ૹͳͲͷ໘ݟͯ͘ΕΔ
ͦͦͳͥඪ४Webٕज़ʹͩ͜ΘΔͷ͔ • Web։ൃऀίϛϡχςΟʹ͔ͬΕΔ • ϥΠϒϥϦݟΛٵऩͰ͖Δ • (͜ΕޙͰ͕͢)PWAήʔϜΞϓϦ࣌Λݟਾ͑ͯͷબ • ϒϥβ͑Δϓϩτίϧ͕ݶΒΕΔ
WebSocketεςʔτϑϧ௨৴ • ΫϥΠΞϯτWebAppʹରͯ͠ܨ͗ͬͺͳ͠ͷঢ়ଶʹͳΔ • WebSocketηογϣϯͷੜଘ͕͍࣌ؒͨΊͦͷؒϦ ιʔεΛઐ༗͢Δ
WebSocketଓΛҡ࣋͠ଓ͚Δඞཁ͕͋Δ
ϦΞϧλΠϜ௨৴εςʔτϑϧ௨৴ • 1ͭͷΫϥΠΞϯτ͕1WebAppΠϯελϯεͱີ݁߹͢Δ • গͳ͘ͱ1ηογϣϯͷؒॊೈͳεέʔϧΞτ(Λ ԣʹ૿͢)ϦΞϧλΠϜ௨৴͕ߦΘΕ͍ͯΔؒͷίʔυ ߋ৽(σϓϩΠ)͕͍͠
ϦΞϧλΠϜ௨৴εςʔτϑϧ௨৴ • εςʔτϑϧ௨৴ͱಉظܕPreforkͷ૬ੑͷѱ͞ • 1ݸͷϓϩηε͕1ͭͷϦΫΤετΛಉظతʹॲཧ • 1ϦΫΤετͷॲཧ͕͍࣌ؒ(ʙ1sec)͜ͱ͕લఏ • 1ϓϩηεͰ1WebSocketηογϣϯΛѲΔͱϓϩηε͠ ͔ΫϥΠΞϯτΛऩ༰Ͱ͖ͳ͍
٧·Δਤ
ࠓ·ͰͷWebΞϓϦ͕ͦͷ·· WebSocketΛΔ͜ͱ͍͜͠ͱ ͕Θ͔ͬͨ
͍͔ʹͯ͠զʑϦΞϧλΠϜ௨৴ʹཱͪ ͔͍͍͑ͷ͔ • ָͰ • Θ͔Γͯ͘͢ɺγϯϓϧͰ • εέʔϧՄೳͰ • ӡ༻͍͢͠ͷ͕΄͍͠
ͦΜͳ͏·͍ ιϦϡʔγϣϯ͋Δͷ͔
ैདྷͷWebΞʔΩςΫνϟ͕WebSocketΛ ѻ͏ͱ͖ͷ͍͠Λཧ • ࣌ؒੜ͖ଓ͚Δ௨৴ηογϣϯΛҡ࣋͢Δͷ͕͍͠ • ௨৴ͱϢʔβΛඥ͚Δͷ͕͍͠ => ͜ͷลϛυϧΣΞʹͤΔͷͲ͏͔ ֎ʹग़͢ͷϚΠΫϩαʔϏεͷߟ͑ํʹ͍͔ۙ͠Εͳ͍
WebSocketηογϣϯΛ ҡ࣋͢Δ͚ͩͷ ϛυϧΣΞ kuiperbeltͷ։ൃͱಋೖ
kuiperbeltͱ • OSSͰ͢3 • WebSocketͷηογϣϯΛड͚ͯҡ࣋͢Δ͚ͩͷ௨৴σʔϞϯ • ࠷ॳݸਓϓϩδΣΫτͰ͕ͨ͠ɺձࣾͰ͔ͳΓΘΕ͍ͯ· ͢ • ձࣾͷਓʹίϛοτͯ͠Β͍ͬͯ·͢
3 https://github.com/kuiperbelt/kuiperbelt
None
None
໊લͷ༝དྷ ఱจֶͷΤοδϫʔεɾΧΠύʔϕϧτ*͔Β * photo by NASA
kuiperbelt͕ग़དྷΔ͜ͱ • WebSocketηογϣϯͷҡ࣋ • HTTP-APIͰͷಛఆηογϣϯͷϝοηʔδͷྲྀ͠ࠐΈ • ্Γ(ΫϥΠΞϯτ->αʔό)ඇରԠ7 7 ରԠ༧ఆ͋Γ
͢͜ͱͷྲྀΕ 1. ౦ژϓϦζϯͰͷαʔόߏͷུ֓ 2. kuiperbeltΛͬͨWebSocketηογϣϯͷೝূɾϝοηʔδ ৴ 3. ઃܭࢥ 4. ࣮ࡍͷӡ༻ࣄྫ
5. ౦ژϓϦζϯͰͷ࣮ࡍͷΘΕํ
౦ژϓϦζϯͷαʔόߏ8 8 ຊ17:50ΑΓฐࣾ౻ݪͷৄ͍͠ߏͷղઆ͕͋Γ·͢
HTTPͷதͷΈͷதͰೝূΛ͢Δ • ೝূWebSocketͷΞοϓάϨʔυલʹWebAppଆʹϓϩΩ γΛߦ͏ • ϓϩΩγ࣌ʹkuiperbeltࣗͷղܾՄೳͳϗετ໊ΛՃ͢ Δ -> εέʔϧΞτʹ༻͍Δ •
WebAppଆϨεϙϯεͷϔομʹࣝผࢠΛՃ͑Δ
HTTPͷதͷΈͷதͰೝূΛ͢Δ
HTTPͷதͷΈͷதͰϝοηʔδ৴Λ ͢Δ • ΫϥΠΞϯτͷϝοηʔδϔομͰࣝผࢠΛࢦఆͯ͠ɺϘ σΟͷ༰ͦͬ͘Γͦͷ··WebSocketͷηογϣϯʹྲྀ͠ ࠐΉ • தͷϝοηʔδͷܗࣜkuiperbeltؔ༩͠ͳ͍ • ౦ژϓϦζϯόΠφϦΛྲྀͯ͠·͢
HTTPͷதͷΈͷதͰϝοηʔδ৴Λ ͢Δ
kuiperbeltࣗͷઃܭࢥ • ୯७ͳ͜ͱ͔͠Βͳ͍ͷͰམͪͳ͍ɾ࠶ىಈ͠ͳͯ͘ྑ͍ • ήʔϜϩδοΫΒͳ͍ͷͰσϓϩΠ͕ඞཁͳ͍ • Ҏ্ӡ༻͍ͯ͠Δ͕ϝϞϦϦʔΫى͖͍ͯͳ͍ • ಛఆϓϩτίϧɾϛυϧΣΞʹґଘ͠ͳ͍
ผλΠτϧͰͷোࣄྫ ͏͔ͬΓHTTP/2ࣄ݅ ݱࡏҰఆִؒͰίωΫγϣϯΛഁغ͢Δ࣮͕ೖ͍ͬͯ·͢
kuiperbeltࣗͷઃܭࢥ • GoͰॻ͔Ε͍ͯΔͷͰίΞ͚ͩͪΌΜͱεέʔϧ͢Δ • 1ίΞ͋ͨΓඵؒ10,000ϝοηʔδ͙Β͍(1ϝοηʔδ͋ͨΓ ฏۉ150bytes) • ϝϞϦྔΫϥΠΞϯτʹൺྫ͠ɺϝοηʔδͷ༰ͳͲ ʹࠨӈ͞ΕΔ͕1ສଓͰ1GBʙ1.8GB
࣮ࡍͷӡ༻Ͱ • ࣮ෛՙࢼݧͰϝοηʔδྲྀྔͱϝοηʔδαΠζ͕େ͖͍͜ͱ ͕໌ͨͨ͠Ίɺ1Πϯελϯε5000ଓఔʹ͑ͨ • m3.large4ͱr4.large5ͷspot fleetʹ͍ͯͨ͠Βm3.largeͷpps ্ݶ͕ͯ͘ภΓ͕ग़ͨͷͰr4.largeͷΈͷӡ༻ʹ͍ͯ͠Δ 5 2core
15.25GBϝϞϦ 4 2core 7.5GBϝϞϦ
ύέοτ٧·ΓΛىͯ͜͠࠶ૹ͕ߦΘΕ͍ͯ Δϩά 21:00:47 plack.1 | 1019.259 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send
| Furl:40 21:00:47 plack.1 | 3017.341 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send | Furl:40 21:00:47 plack.1 | 1017.801 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send | Furl:40 21:00:47 plack.1 | 7174.359 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send | Furl:40 21:00:47 plack.1 | 1025.966 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send | Furl:40 21:00:47 plack.1 | 10010.330 ms [Furl::HTTP] POST http://XX.XX.XX.XX:9180/send | Furl:40 1, 3, 7, 10...ͱԆ͍ͯ͠ΔͷͰ࠶ૹͰ٧·͍ͬͯΔͷͰʁ ͱ ͳͬͨ
͍ͬͯΔ͜ͱ͕γϯϓϧͳͷͰ༷ʑͳΞʔΩςΫνϟʹରԠͰ͖Δ MO͖ͷதܧ͚ͩߦ͏ΞʔΩςΫνϟ
͍ͬͯΔ͜ͱ͕γϯϓϧͳͷͰ༷ʑͳΞʔΩςΫνϟʹରԠͰ͖Δ MMOϚονϯά͖ͷαʔόͰήʔϜϩδοΫΛ࣮ߦ͢ΔΞʔΩςΫνϟ
ϦΞϧλΠϜ௨৴αʔόΛϩʔυόϥϯαʔʹΈࠐΉ Q: ෳͷαʔόΛܦ༝͢Δ͔ΒϨΠςϯγ͕ݫ͍͠ͷͰʁ A1: ϞόΠϧʹ͓͍ͯͦͷݶΓͰͳ͍ A2: λʔϯ੍ͳΒ͋Δఔڐ༰Ͱ͖Δ
A1: ϞόΠϧʹ͓͍ͯͦͷݶΓͰͳ͍ HTTP-APIΛଧ͔ͬͯΒWebSocketͰԠ͕͔͑ͬͯ͘Δ·Ͱͷ RTTΛܭଌ6 6 JavaScriptͳͷͰspectreͷӨڹͰ2msఔͷؙΊ͕ଘࡏ͍ͯ͠Δͷཹҙ
A1: ϞόΠϧʹ͓͍ͯͦͷݶΓͰͳ͍ • લ͕ݻఆޫճઢܦ༝ͷWiFi, ޙ͕4G • WiFiͩͱ20 ʙ 30ms, 4Gͩͱ75msʙ
• LBΛܦ༝͢Δ͜ͱʹΑΔϨΠςϯγ1ܻmsఔ • ϞόΠϧʹ͓͍ͯLBʹΑΔϨΠςϯγࢧతͰͳ͍
A2: λʔϯ੍ͳΒ͋Δఔڐ༰Ͱ͖Δ • ͜Ε͕PCίϯγϡʔϚͰΔΑ͏ͳFPS֨ήʔͰ͋Ε1ܻ msͷԆͰ͢Βॖ͍ͨ͠ • ڐ༰͞ΕΔԆ෯ήʔϜγεςϜʹΑͬͯมΘΔ • ཁ݅ʹΑͬͯૹΓͬͺͳ͠ʹͰ͖Δ/Φʔόʔϔου͕গͳ ͍UDPͳͲΛબ͢Δ
ݱঢ়LBʹೖΕΔϝϦοτ͕Ͱ͔͍ • TLS TerminationΛͤΔ͜ͱ͕ग़དྷΔ • ݸผʹTerminationΛ͍ͬͯΔͱূ໌ॻͷཧ͕໘ • ࠷ۙ௨Βͳ͍ϑΥϫʔυϓϩΩγ͕ݮͬͨͱ͍͑ੜ WebSocketૄ௨͢Δ͔Ͳ͏͔ͷϦεΫ͕͋Δ
ݱঢ়LBʹೖΕΔϝϦοτ͕Ͱ͔͍ • ࣗಈͰ༙͍ͨԾϚγϯ/ίϯςφʹ౸ୡՄೳͳIPΞυϨε/ϗ ετΛͲ͏ͬͯΫϥΠΞϯτʹ௨͢Δ͔ • ैདྷಉ͡ϧʔϜΛݻΊΔΑ͏ʹϚονϯά࣌ʹଓ͖͢ ΞυϨεΛࣔͨ͠Γ • LBͳΒೖΕΔ͚ͩͰ౸ୡՄೳʹͳΔɺϧʔϜͰݻΊΔΈ͍ͨ ͳͷग़དྷͳ͍͕
࣮ࡍʹΈࠐΜͰΈͯ౦ژϓϦζϯ ͲͷΑ͏ʹήʔϜΛਐߦ͍ͯ͠Δ ͔
kuiperbeltΛΈࠐΜͩ౦ژϓϦζϯͷॲཧ
kuiperbeltΛΈࠐΜͩ౦ژϓϦζϯͷॲཧ
ήʔϜϩδοΫ͕αʔόଆʹ͋Δ͜ͱͷϝ Ϧοτ • ήʔϜϩδοΫͷมߋ͕͋Δఔ༰қ ετΞਃ͕ཁΒͳ͍ • ΫϥΠΞϯτੑೳʹҾͬுΒΕͳ͍ • ΫϥΠΞϯτ։ൃऀֆΛग़͢͜ͱʹूதͰ͖Δ •
νʔτ͞Εʹ͍͘ • ϩΪϯά༰қͳͷͰղੳͳͲͰ͖Δ
ήʔϜϩδοΫ͕αʔόଆʹ͋Δ͜ͱͷσϝ Ϧοτ • ΫϥΠΞϯτ͕αʔόͷॲཧΛͭͨΊϨεϙϯγϏϦςΟ͕ ѱ͍ • αʔόͷϨεϙϯεΛͨͳ͍ͳͲͷରࡦΛߨ͍ͯ͡Δ(ඇಉ ظԽ)
ήʔϜϩδοΫ͕αʔόଆʹ͋Δ͜ͱͷσϝ Ϧοτ • αʔόͷෛՙରࡦΛेʹߦ͏ඞཁ͕͋ΔɹϦιʔε֬อ͢ Δඞཁ͕͋Δ • ఆ࣮ෛՙࢼݧͱνϡʔχϯάΛ܁Γฦ͠·͕ͨ͠ඇৗʹۤ ࿑͠·ͨ͠
ͦͷଞkuiperbeltΛಋೖͨ͜͠ͱͰݟ͖͑ͯͨ 1. ϝοηʔδ౸ୡॱ 2. αʔόؒϝοηʔδܽଛ
ϝοηʔδ౸ୡॱ kuiperbeltͷதͰϩοΫऔΕͨॱ൪ʹྲྀΕΔ
ϝοηʔδ౸ୡॱ ղ๏ • γʔέϯε൪߸Λ্ͨͤͨͰ 1. ΫϥΠΞϯτଆͰόοϑΝϦϯάͭͭ͠ฒ͢ 2. kuiperbeltଆͰόοϑΝϦϯάͭͭ͠ฒ͢
ϝοηʔδ౸ୡॱ ΫϥΠΞϯτଆͰฒ͢ͷΛ࠾༻ • kuiperbeltͰΔͱϝϞϦ༻ྔ͕૿͑Δ, ঢ়ଶ͕૿͑ͯίϯς φ͕མͪͨͱ͖ʹϝοηʔδܽଛ͕૿͑Δ • ඈͦ͏ͱͨ͠ϝοηʔδͬ͞͞ͱૹͬͯঢ়ଶΛͳ͘͢ • kuiperbeltதʹྲྀΕΔσʔλʹؔ༩͠ͳ͍ϧʔϧ
αʔόؒϝοηʔδܽଛ • HTTPͰૹΔͱܽଛ͢ΔΜ͡Όͳ͍ʁʁʁ • DC௨৴, Ϧʔδϣϯ௨৴ͳͷͰܦ࿏ͰམͪΔ͜ͱͳ͔ ͳ͔ͳ͍ • ϦτϥΠ&ΫϥΠΞϯτଆͰͷॏෳݕͳͲೖΕ͍ͯΔ •
ࠓޙcircuit breakerೖΕΔ
ͦͯ͠ӡ༻͍ͯ͠Δࠓ • αʔόͷਓ͕͋Μ·ΓWebSocketͷ͜ͱΛߟ͑ͣʹࠓ·ͰͲ͓ ΓίʔυΛॻ͚Δ • WebSocketαʔό͕ίϯςφͱϩʔυόϥϯαʔʹΑͬͯϊʔ ϝϯςͰಈ͍͍ͯΔ • ͍ͭͰίϚϯυҰൃͰεέʔϧΞτՄೳ •
WebSocketͷ͜ͱΛ͋·Γߟ͑ͣʹσϓϩΠ͕ग़དྷΔ
εέʔϧՄೳͰ ӡ༻͍͢͠ WebSocketαʔό ͕ಈ͍͍ͯΔ
·ͱΊ • ैདྷͷWebΞϓϦέʔγϣϯΞʔΩςΫνϟʹൺֱత༰қʹಋ ೖͰ͖ΔϦΞϧλΠϜ௨৴༻ϛυϧΣΞΛ࡞࣮ͬͯࡍʹຊ൪ ಋೖ͠·ͨ͠ • ଞͷطʹӡ༻தͷήʔϜʹಋೖ͢Δχʔζ͕͋ΔΑ͏ͳͷͰ ͜Ε͔Β͍͖ͬͯ·͢ • ຊ൪ӡ༻ͯ͠ΈͯɺղܾՄೳͰ͋Δ͕ɺͦͦ͜͜ͷ͍
͔ͭ͘߹ͬͨͷͰڞ༗͍͖ͤͯͨͩ͞·ͨ͠
Any Questions?