ISUCON'Makers'Casual'TalksISUCON'32014/12/10&@fujiwara
View Slide
About&me@fujiwaraISUCON'1,'2'༏উ'(fujiwara)ISUCON'3'ग़໘ന๏ਓΧϠοΫ
ग़ͷܦҢISUCON'1,'2'fujiwara࿈ʂ2ͷ࠙ձʮग़͍ͯͩ͘͠͞Αʯʮ͍ʂʯCROSS%2013%@941͞Μʹ͓ئ͍͞ΕΔ
Timeline2013/1&CROSS&20132013/4'ΧϠοΫٕज़෦৽ଔݚमʮࣾISUCONʯ2013/6'@941͞ΜͱϛʔςΟϯά2013/7/31'ग़࡞ઓձٞ2013/9/21'YAPC::Asia'2013'ʮࣾISUCONͷͭ͘Γ͔ͨʯൃද2013/10/5,6)ISUCON)3)ΦϯϥΠϯ༧બ2013/11/9'ISUCON'3'ຊબ
ISUCON'1,2'ͱ'3'ͷҧ͍ΦϯϥΠϯ༧બ2ճɺผͷΛ࡞Δ
ࣾISUCON৽ଔݚमͷҰओʹαʔόαΠυΛΔΤϯδχΞ͚HTTPΛֶͿ$→$WebΞϓϦΛ࡞Δ࡞ͬͨΞϓϦͰISUCON!github.com/kayac/newbie2training
ࣾISUCONݚमͷҰͷͨΊૉͳग़• ੩తϑΝΠϧΛΞϓϦαʔό͕৴• ΠϯσοΫε͕ுΒΕ͍ͯͳ͍ςʔϒϧ• ϧʔϓதͰΫΤϦ͕ඈͿ੩తϑΝΠϧΛwebαʔό৴$+$ΠϯσοΫεΛదʹுΔ$+$ϧʔϓΫΤϦΛJOINʹॻ͖͑→$είΞ20ഒ
ࣾISUCONͰͷܦݧ• Ր༵"WebAppॻ͘• ਫ༵"ςετॻ͘• ༵"ϕϯνϚʔΫॻ͘• @acidlemon"ʹղ͍ͯΒ͏• ༵ۚே͔Β"ISUCON(னؒݚमͷߨࢣۀ)
ࣾISUCONͰͷল• ్தͰϕϯνϚʔΫϗετ"㱻"֤VMͷଳҬةͳ͍• ଳҬ͕͢ΔͱείΞ͕͔ࠩͳ͘ͳΔ• ్தͰ"Accept-Encoding: gzip"Ճ
2013/7/31ग़࡞ઓձٞ!@fujiwara! !@acidlemon!@typester! !@songmu
memoը૾ϦαΠζಉ࣌ଓܥɺνϟοτɺϨΠςϯγpush͔ΒͷҰ੪ΞΫηεΛΤϥʔʹ͠ͳ͍Ͱ͑ΔಉใRedisͬͯΔ͚Ͳ͍ํѱ͍mongogithref=""PostgreSQLೖΕ͓ͯ͘
ຊબʹ࠾༻• ը૾ϦαΠζ• ಉ࣌ଓܥɺϨΠςϯγ• Ұ੪ΞΫηε༧બʮຊબͷωλόϨʹͳΒͳ͍ʯͷ
10/5,6'ΦϯϥΠϯ༧બ
༧બग़༰Github'GistͷΑ͏ͳͷϩάΠϯػೳɻCookieʹΑΔηογϣϯҡ͕࣋ඞཁϓϥΠϕʔτߘػೳɻϓϥΠϕʔτઃఆ͞ΕͨͷϩάΠϯ͍ͯ͠ΔϢʔβࣗʹ͔͠ݟ͑ͳ͍MarkdownܗࣜͰߘʴ!᠘తͳઃఆ
༧બͷҙਤ໌Β͔ʹຊબग़ʹ࣮ྗͷΓͳ͍νʔϜΛ;Δ͍མͱ͢×"੩తϑΝΠϧΛΞϓϦαʔό͕৴×"ΠϯσοΫε͕ͳ͍ςʔϒϧ×"ϧʔϓΫΤϦ×"Markdownมʹ֎෦ίϚϯυىಈී௨ͷWebΞϓϦͱͯ͠μϝͳ࣮ΛͤΕߴείΞʹʴ$Ϙʔφεͱͯ͠ʮ᠘ʯΛΫϦΞͯ͠Ճ
༧બ४උʙ!9/17!ग़ͷϓϩτλΠϓGoͷϕϯνΫϥΠΞϯτԾ࣮9/25ʙ%@acidlemon%ʹղ͍ͯΒ͍͡ΊΔ9/30%/recent/*%ΛՃ10/2,3'Ruby,'Python,'Go,'Node,'PHP'Ҡ২10/5,6'ISUCON3'༧બ
༧બ͔ࣗΒIRCͰαϙʔτ
༧બͷʮ᠘ʯ
MySQL&InnoDB&memcached&pluginMySQL&5.6ͷ৽ػೳ• memcached(protocolͰMySQLͱ௨৴Ͱ͖Δ• port(11211(Λ(Listen• ΞϓϦέʔγϣϯ͔Βηογϣϯอଘʹ༻• port(11212(Ͱී௨ͷ(memcached(ىಈͯ͋͠Δ• ॳظঢ়ଶͰ༻͍ͯ͠ͳ͍
ҙຯͷͳ͍!CSS!link• ϕϯνϚʔΧʔϦϯΫΛḷͬͯ"/"ʹϦΫΤετΛඈ͢• ͔͠͠είΞ"0• PageViewͰͳ͍ͱ͍͏ѻ͍• HTML͔Βআ͢ΔͱϦΫΤετ͠ͳ͘ͳΔ
ҰൃΞτͰͳ͍ݮํࣜfail=3·Ͱݮͳ͠failͷࣗ%&(ͨͱ͑&fails=6&ͳΒ& )&Λݮfail%>=%13%Ͱ% %ݮʹͳΔͷͰείΞ%0
༧બͷল• είΞϦϯάͷৄࡉ͕ެ։͞Ε͍ͯͳ͔ͬͨ• /recent/*"ʹର͢ΔϕϯνϚʔΧʔͷνΣοΫ͕͔ͬͨ• ͋ͱ͔ΒՃͨ͠෦• ͜͜Λ"Cache"͢ΔͱΑ͘ճΔ
༧બϕϯνϚʔΧʔ• Go• ࢀՃऀ͕ࣗ༝ʹͳΔϗετͰಈ࡞͢ΔͨΊɺղੳ͞Εʹ͍͘Α͏ʹ• --workload$Φϓγϣϯॳಋೖ• ISUCON$1,2ͰௐͰ͖ͳ͔ͬͨ
༧બϕϯνϚʔΧʔ• ੩తϑΝΠϧ͚ͩΞΫηε͢Δ"sta&c"worker• ϦΫΤετ͝ͱʹ"10ms"wait• /recent/*"͚ͩΞΫηε͢Δ"recent"worker• ϩάΠϯɺߘɺӾཡɺϩάΞτɺӾཡΛ܁Γฦ͢"main"worker
༧બϕϯνϚʔΧʔ!͕߹ܭ!worker!w=1$>$ $(sta*c=1,$recent=1,$main=6)w=2$>$ $(sta*c=2,$recent=2,$main=14)w=3$>$ $(sta*c=3,$recent=3,$main=28)
༧બϕϯνϚʔΧʔͷʮ݀ʯrecent&worker&• wait&ͳ͠ʹճΔ• දࣔཁૉ͕ߋ৽͞Ε͍ͯΔ͔Ͳ͏͔ͷνΣοΫΛͯ͠ͳ͍ʂʂʂ/recent/*!ΛΩϟογϡͯ͠ߴʹฦ͢ͱ!είΞ↑↑
༧બͷলείΞࢉग़ͷৄࡉެ։͢͠աͳʮ᠘ʯΑ͘ͳ͍ϕϯνϚʔΧʔͷ݀Ͱ͖ΔݶΓ௵͢͠
11/9$ຊબ
ຊબग़ʹͨͬͯʮ᠘ʯΊΑ͏ෳαʔόΛ༗ޮʹ͑Δग़ʹ͠Α͏
ຊબ୲!@fujiwara!ɺϕϯνϚʔΫɺείΞूܭγεςϜ!@acidlemon!ࣄલղɺϕϯνϚʔΫνΣοΫɺΦʔϓχϯάɺϨΪϡϨʔγϣϯ!@handlename:!nodeҠ২ɺಈ࡞֬ೝ!@mix3:!GoҠ২ɺಈ࡞֬ೝ!@nobu_ohta:!RubyҠ২ɺPythonҠ২!@m0t0k1ch1:!PHPҠ২ɺ෧σβΠϯ
ຊબ४උ10/17%ΩοΫΦϑ10/29%ग़ͱϕϯνϚʔΧʔϓϩτλΠϓͰղ͖࢝ΊΔ%ଟݴޠҠ২։࢝11/5%5ߏͰղ͘,%ຊ൪༻αʔόࠐΈ11/7%ຊ൪αʔό্Ͱςετ։࢝11/8%݁Ռूܭը໘࡞ɺσόοά11/9%ISUCON3%ຊબ
ຊબग़༰ը૾ߘ͕Ͱ͖ΔSNSHTMLΛฦ͢෦ͳ͘ɺJSON)APIͷΈϢʔβΛϑΥϩʔͰ͖ΔɻϑΥϩʔ͍ͯ͠ΔϢʔβͷߘ͕ྲྀΕͯ͘ΔLong%polling%API%͋ΓϕϯνϚʔΧʔը૾Λߘͨ͠ΓJSONΛऔಘͨ͠Γ͢Δ
είΞࢉग़ํ๏Լهͷ!(a)+(b)+(c)!͕૯߹είΞ(a)$ߘεϐʔυ$=$ϨεϙϯελΠϜ͕͍΄ͲߴείΞ(b)$λΠϜϥΠϯө$=$ߘͨ͠ΤϯτϦͷใ͕ө͞ΕΔͷ͕͍΄ͲߴείΞ(c)$ͦͷଞϦΫΤετ$=$1
είΞࢉग़ํ๏ϨεϙϯελΠϜʹґଘ͢ΔείΞҎԼͷܭࢉࣜʹΑΔ5"sec"="11"sec"="3.3100"msec"="6.6410"msec"="9.9
ຊબͷϙΠϯτ5ͷαʔόΛͲ͏͏͔ॳظঢ়ଶͰ1ͷΈʹΞϓϦέʔγϣϯ͕ىಈ͍ͯ͠Δ2ʙ4ʮۭʯ(OSɺϛυϧΣΞͷॳظઃఆͷΈ)ଳҬ1͋ͨΓ• eth0&:&100Mbps&(ϕϯνϚʔΧʔ͕ΞΫηε)• eth1&:&1Gbps&(ࣗ༝ʹ͑Δ)
ຊબͷϙΠϯτը૾ͷϦαΠζΛ͍ͭߦ͏͔ॳظঢ়ଶϦΫΤετ͝ͱʹຖճಈతੜ1. ߘ࣌ʹ#S,#M,#L#ͷ3αΠζ#+#ΦϦδφϧΛશͯੜ͠อଘ2. ߘ࣌ΦϦδφϧͷΈอଘ͠ɺαϜωΠϧӾཡ࣌ʹੜ※!શͯͷαϜωΠϧ͕ϦΫΤετ͞ΕΔΘ͚Ͱͳ͍
ຊબͷϙΠϯτը૾ͷϦαΠζΛԿͰߦ͏͔ॳظ࣮!ImageMagick!convert!ίϚϯυΛ(֎෦)࣮ߦ• ը૾ϥΠϒϥϦʹΑͬͯม݁Ռʹࠩҟ͕ͰΔ• ը૾Λൺֱ͢ΔπʔϧΛఏڙɻϦϑΝϨϯε࣮ͱͷޡ͕ࠩҰఆҎԼͰͳ͍ͱfail
ຊબͷϙΠϯτLong%poll%API%ΛͲ͏ߴԽ͢Δ͔ॳظ࣮2ඵsleepͯ͠ฦͤΔͷ͕͋Δ͔νΣοΫ• ฏۉϨεϙϯελΠϜ͕1ඵʹͳΔ• ԿΒ͔ͷΠϕϯτ௨Λར༻ͯ͠ߴʹөͰ͖ΔͱߴείΞ
ຊબͷϙΠϯτଳҬΛ͍͔ʹຒΊΔ͔ϕϯνϚʔΧʔ࠷େ!100Mbps! !5!=!500Mbps!Λ͑ΔͰ͖Δ͚ͩଟ͘ͷϗετ͔Β৴͢ΔͱଳҬΛ༗ޮʹ͑Δ
ຊબϕϯνϚʔΧʔPerl%(Furl%+%AnyEvent)post:&ΞΠίϯͱΤϯτϦΛPOSTɺαϜωΠϧΛGETͯ֬͠ೝview:&ը૾ΛGET&(0.5&sec&sleep)check:&ϢʔβݖݶʹΑΓݟ͑Δݟ͑ͳ͍ͷݖݶνΣοΫcrawl:&·ͣϩάΠϯ͔ͯ͠ΒλΠϜϥΠϯ(Long&poll)ʹுΓ͘?meline:&λΠϜϥΠϯʹுΓ͖ɺྲྀΕ͖ͯͨϢʔβΛfollowɺը૾ΛGETͳͲ6"process(post,"view,"check,"crawl"֤×1"5meline"×"2)"/"workload
ຊબϕϯνϚʔΧʔͷଳҬ੍ޚLVS$Ͱ$localhost:[νʔϜʹରԠ͢Δport]$͔Βϕϯν૬खʹ$NATϕϯνϚʔΫϦΫΤετ࣌ʹ!NAT!ઌͷෳϗετΛ!on!/!offQoS$github.com/matsumoto1r/qos1controltc#ͷ#wrapper.#100Mbps#ʹ੍ݶ
ຊબͷলଟগͷτϥϒϧ͋ͬͨͷͷ͓͓ΉͶָ͠ΜͰ͑ͨ• ϕϯνϚʔΧʔͷෳΓସ͑όά• Pythonॳظ࣮Ͱ·Εʹ(Fail(͢Δ• tmpfile(ͷ(flush(λΠϛϯά࠷ޙ!Fail!͢ΔνʔϜ͕ଟ͔ͬͨͷ͕೦