æè¿ãhabrã§ivi.ruã§ã®åæã®å®è£
æ¹æ³ã«é¢ãã
åºçç©ããããŸããã èªãã åŸã1ââã€ã®å€§ããªãµã€ãã§è¡ã£ãåæã«ã€ããŠã話ããããã£ãã®ã§ãã æ®å¿µãªããã顧客ã¯èšäºå
ã®ãµã€ããžã®ãªã³ã¯ãå
¬éã§ããŸããã§ããã Alexa Rankãä¿¡ããŠããå Žåãåæãè¡ã£ããµã€ãã®ãã©ãã£ãã¯ã¯ivi.ruã®10åã§ãã
åæãäœæããçç±ãšç®æš
ãµã€ããžã®ã¢ã¯ã»ã¹æ°ãå€ããããããæç¹ã§GoogleãããµãŒãã¹ã®äœ¿çšãåæ¢ãããããªã¯ãšã¹ãã®æ°ãæžããããã«ãšã®æçŽãå±ããäžéšã®ããŒã¿ã¯Googleã¢ããªãã£ã¯ã¹ããååŸã§ããŸããã§ããã
ãŠãŒã¶ãŒã«ã€ããŠåéããæ
å ±ïŒ
- ããŒãžãã¥ãŒïŒåç
§ãIPãUAgentãç»é¢ãµã€ãºïŒ;
- ã¢ã¯ãã£ã/ããã·ã;
- ãããã¡ãªã³ã°;
- å·»ãæ»ããŸãã
åçã®çŽ70ïŒ
ã¯ãããªãã¬ãŒã€ãŒã®ããããŒãžã§ãäž»ãªã¿ã¹ã¯ã¯ãããã®ããŒãžããæ
å ±ãåéããããšã§ããã ã¢ã¯ãã£ã/ããã·ãã«é¢ããæ
å ±ãååŸããå¿
èŠããããŸãã-ãŠãŒã¶ãŒãããŒãžã§ã¢ã¯ãã£ãã ã£ãç§æ°ãããã³éã¢ã¯ãã£ãã§ãã£ãç§æ°-ã¿ããšããŠéãããŸããã ãããã¡ãªã³ã°ã«é¢ããæ
å ±ïŒãããªãã¹ããŒããŠã³ãããã©ããããŠãŒã¶ãŒãããŠã³ããŒãããã®ã«ãããæéïŒãå·»ãæ»ãã®åæ°ãããã³2çªç®ã®ãŠãŒã¶ãŒãå·»ãæ»ãå
ã®æ
å ±ãèå³æ·±ããã®ã§ããã ãããè¡ãããã«ããã¹ãŠã®ããŒãžã«JavaScriptã³ãŒããé
眮ããããã©ãŠã¶ã§éããããŒãžãããµãŒããŒæ
å ±ã«30ç§ããšã«ã¿ãããããŸããã
ã¯ã©ã€ã¢ã³ãéš
ãã®ã¹ã¯ãªããã¯éåžžã«åçŽã§ãåæãµãŒããŒãã2ã€ã®1ãã¯ã»ã«ç»åãååŸãããããã®ç»åã®URLã«ãã©ã¡ãŒã¿ãŒãæž¡ããŸãã ãªããã ç§ãã¡ã®æèŠã§ã¯ãæãä¿¡é Œã§ãããœãªã¥ãŒã·ã§ã³ã¯ãã©ã®ãã©ãŠã¶ãŒãšãã©ãããã©ãŒã ã§ãå®å
šã«æ©èœããŸãã AJAXã䜿çšããå Žåã¯ãããŸããŸãªãã©ãŠã¶ãŒã®ã¯ãã¹ãã¡ã€ã³ãšããã©ãŒãã³ã¹ã®åé¡ã解決ããå¿
èŠããããŸãã stat.gifãšp.gifã®2ã€ã®ç»åããããŸããæåã®ç»åã¯ããŒãžã®èªã¿èŸŒã¿æã«äœ¿çšããããŠãŒã¶ãŒã«é¢ããåºæ¬æ
å ±ãéä¿¡ããŸãã2çªç®ã®ç»åã¯15ç§ããšã«åããæéãšãšãã«å€åããæ
å ±ïŒã¢ã¯ãã£ã/ããã·ãããããã¡ãªã³ã°ãå·»ãæ»ãïŒã転éããŸãã
ãã®ç»åã¯ãæåã«ããŒãžãéãããšãã«åæºããŸãã
/stat.gif?pid=p0oGejy139055323022216801050bny0&l=http%3A%2F%2Fsite.ru%2F8637994&r=http%3A%2F%2Fsite.ru%2F&w=1680&h=1050&a=Mozilla%2F5.0%20(Windows%20NT%206.1%3B%20rv%3A26.0)%20Gecko%2F20100101%20Firefox%2F26.0&k=1390553230222&i=30000&vr=3.0
ãã®åçã¯30ç§ããšã«ã²ãã€ããŸãïŒ
/p.gif?pid=p0oGejy139055323022216801050bny0&rand=6752416&b=1&time=2-188x190-57x50-349x251-83x0-235x&pl=29&fpl=46&ld=552&efsc=true&tfsc=19&tac=89&tpas=70&vr=3.0
ãã©ãã£ãã¯ãæžããããã«ããã©ã¡ãŒã¿åã¯çç¥ãããŠããŸãã PID-ããŒãžã衚瀺ããããã®äžæã®èå¥åã¯ãstat.gifããã³p.gifããã®ããŒã¿ãšäžèŽããããã«æ©èœããŸãã
ãµãŒããŒåŽ
ç§ãã¡ã¯ããã«ããŒã¿ããŒã¹ã決å®ããMongoDBã䜿çšããããšã«ããŸããïŒã¯ã€ãã¯ã€ã³ãµãŒããããŒã¿ã¯ããã¥ã¡ã³ãã«æ ŒçŽãããéãªã¬ãŒã·ã§ãã«æ§é ïŒã æåã®å®è£
ã¯phpã§æžãããŠãããéãè² è·ã®äžã§ã®æåã®ãã¹ãã¯æ·±å»ãªåé¡ã瀺ããŸããã
- php-fpmèªäœã¯ãnginxãšçµã¿åãããŠããªã¯ãšã¹ããåŠçããããã«å€ãã®ãªãœãŒã¹ãæ¶è²»ããŸããã
- stat.gifãMongoDBã«ããŒãããããšãæ°ããããã¥ã¡ã³ããæ¿å
¥ããã15ç§ããšã«p.gifã€ã¡ãŒãžã«ä»å±ããããŒã¿ãæŽæ°ãããŸããã
stat.gifãšp.gifããã®ããŒã¿ãéçŽããŠmonguã«æ¿å
¥ããå¿
èŠãããã®ã¯ãèŠæ±ãp.gifãžã®éä¿¡ãåæ¢ããåŸã«ã®ã¿æããã«ãªã£ãã ããã«ãããMongoDBã®åŒã³åºãåæ°ã1æ¡æžããããšãã§ããåŒã³åºãèªäœã¯æ¿å
¥æã®ã¿ïŒæŽæ°ãªãïŒã«ãªããŸããã PHPã®åé¡ã解決ã§ããªããããæ°ãããã©ãããã©ãŒã ãéžæããããšã«é¢ããŠçåãçããŸããã WebãµãŒããŒã¬ãã«ã§ãªã¯ãšã¹ããåŠçããæ©èœãå¿
èŠã ã£ããããNodeJSãããã«éžæãããŸããã çç±ïŒéåææ§ãçŽæã銎æã¿ã®ããæ§æïŒJavaScriptã®è±å¯ãªçµéšïŒãã³ãŒãã®èšè¿°ã®æ¯èŒç容æãã NodeJSãæ¯æããéžæã«å€§ããªåœ±é¿ãäžããã®ã¯ãashtuchkinã«ããåºçç©
ãNode.jsã§ã®çŸäžã®åææ¥ç¶ã ã§ãã ããµãŒããŒã§èª¬æããå®éšãç¹°ãè¿ããŸããã
ãã©ãã£ãã¯ãšãªã¯ãšã¹ãã®æ§è³ªã«ã€ããŠå°ãïŒéããŠãããã¹ãŠã®ããŒãžã«ãã®ãããªã¹ã¯ãªãããããã15ç§ããšã«ãµãŒããŒã«ããŒã¿ãã¿ããããŸãã 1人ã®ãŠãŒã¶ãŒããã®ãããªããŒãžãäžåºŠã«è€æ°éãããšãã§ãããŠãŒã¶ãŒããã®ããŒãžãéããŠãããã©ããã«é¢ä¿ãªãããã¹ãŠã®ããŒãžãããŒã¿ãéä¿¡ããŸãã ããã ãã§1æ¥ãããçŽ4,000äžåã®èŠèŽããããŸãã
NodeJSäžã®ãµãŒããŒããã€ã¹
æåã«ããã¹ãçšã«ãµãŒããŒã®ã·ã³ã°ã«ã¹ã¬ããããŒãžã§ã³ãäœæããŸããã ãã®ã¹ã¯ãªããã¯éåžžã«åçŽã§ãstat.gifããã³p.gifã®ç»åã®ãªã¯ãšã¹ããåä¿¡ãããã®ããŒã¿ãé
åã«æžã蟌ã¿ãŸãã
Array ( [PID] => Array ( [stat] => stat.gif [pgif] => p.gif ( 15 ) [time] => , PID ) )
ããã«ã¿ã€ããŒã§ããã³ãã©ãŒãèµ·åãããPIDã䜿çšããŠã¢ã¬ã€å
šäœãå埩åŠçãããã®PIDã«ããæåŸã®ããŒã¿å€æŽã®æå»ããã§ãã¯ããŸãïŒArray [PID] [time]ïŒã æåŸã®å€æŽãã90ç§ä»¥äžãçµéããå ŽåïŒããŒã¿ã15ç§ããšã«ãŠãŒã¶ãŒããå±ããªãããããŠãŒã¶ãŒãããŒãžãéããããã€ã³ã¿ãŒããããæ¶ããããšãæå³ããããïŒãã¬ã³ãŒãã¯MongoDBã«æ¿å
¥ãããã¢ã¬ã€èªäœããåé€ãããŸãã ã·ã³ã°ã«ã¹ã¬ããããŒãžã§ã³ããã¹ãããåŸããã«ãã¹ã¬ããããŒãžã§ã³ãå®è£
ããããšã決å®ãããŸããïŒãã¹ãŠã®ããã»ããµæ©èœãæ倧éã«æŽ»çšããããïŒã
NodeJSã§ã¯ãçŽ æŽããã
Clusterã¢ãžã¥ãŒã«ã®ãããã§ãã«ãã¹ã¬ãããéåžžã«ç°¡åã«å®è£
ãããŸãã ãã®èšäºã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ããã«ãã¹ã¬ããã³ãŒãã®è©³çŽ°ã«ã¯è§ŠããŸããïŒããã«ã€ããŠã¯ããŸã説æããŠããŸããïŒããã®ã¢ãžã¥ãŒã«ã䜿çšãããšãç°ãªãã¹ã¬ããã®è€æ°ã®ã€ã³ã¹ã¿ã³ã¹ã§ã³ãŒãã®äžéšãå®è¡ã§ããã¡ãã»ãŒãžã䜿çšããŠã¡ã€ã³ã¹ã¬ãããšåã¹ã¬ãããããåãããããã®ããŒã«ãæäŸããŸãã
ã·ã³ã°ã«ã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯ã¯ããããã¹ã¬ãããšåã¹ã¬ããã«åããããŸããã
åã¹ããªãŒã ã¯httpãªã¯ãšã¹ããåä¿¡ãã1ãã¯ã»ã«ã®ç»åãè¿ããgetãªã¯ãšã¹ãã®ç»åãšãšãã«åä¿¡ããããŒã¿ã¯ãããã¹ããªãŒã ã«éä¿¡ãããŸããã
worker-ïŒåã¹ããªãŒã ïŒã®ã³ãŒãäŸïŒ
ããŒã¿ã¯ã
process.sendïŒ{}ïŒã䜿çšããŠãããã¹ããªãŒã ã«éä¿¡ãããŸãã
ãããã¹ããªãŒã ã§ã¯ãåã¹ããªãŒã ããã®ããŒã¿ã¯
worker.onïŒ 'message'ãfunctionïŒdataïŒ{}ïŒãããŠé
åã«æžã蟌ãŸããŸãã
ãµã³ãã«ãããã¹ããªãŒã ã³ãŒãïŒ
, worker.on('message', function(data) { switch(data.routeType){ case 'p.gif': counter++; if(data.params.pid != undefined && dataObject[data.params.pid] != undefined){
ãŸããã¿ã€ããŒãã¡ã€ã³ã¹ã¬ããã§èµ·åãããé
åå
ã®ãšã³ããªãåæããã90ç§ä»¥äžå€æŽããªãã£ããã®ãMongoDBããŒã¿ããŒã¹ã«æ¿å
¥ãããŸãã
ããŒã¿ä¿å
ããŒã¿ã¹ãã¬ãŒãžã«ãç¬èªã®åŸ®åŠãªéãããããããããŸããŸãªå®éšäžã«ããã¹ãŠã®ããŒã¿ã1ã€ã®ã³ã¬ã¯ã·ã§ã³ïŒMySQLã®ããŒãã«ã®é¡äŒŒç©ïŒã«æ ŒçŽããã®ã¯æªãèãã§ãããšããçµè«ã«éããŸããã æ¯æ¥æ°ããã³ã¬ã¯ã·ã§ã³ãäœæããããšã決å®ãããŸãã-MongoDBã®å©ç¹ã¯ç°¡åã§ããã³ã¬ã¯ã·ã§ã³ãååšãããäœããæžã蟌ãããšãããšãèªåçã«äœæãããŸãã ãã®äœæ¥ã®éçšã§ããµãŒããŒåŽã¯ååã«æ¥ä»ãå«ãããŒã¿ãã³ã¬ã¯ã·ã§ã³ã«æžã蟌ã¿ãŸãïŒstat20141102ãstat20141103ãstat20141104ã
ããŒã¿ããŒã¹æ§é ïŒ
1ã€ã®ããã¥ã¡ã³ãã®æ§é ïŒ1ã€ã®ããã¥ã¡ã³ãã¯1ã€ã®ãã¥ãŒã«å¯Ÿå¿ããŸãïŒïŒ
1æ¥ã®ããŒã¿ã®ééã¯ããªãé©åã§ã-çŽ500ã¡ã¬ãã€ãã¯1/10ããµã³ããªã³ã°ããããšãã§ãïŒèšªåè
ã®10ïŒ
ã®ã¿ãçµ±èšã§ãïŒããµã³ããªã³ã°ãªãã§å®è¡ãããå Žåãã³ã¬ã¯ã·ã§ã³ã®ééã¯1æ¥ã«5ã®ã¬ãã€ãã«ãªããŸãã çããŒã¿ãå«ãã³ã¬ã¯ã·ã§ã³ã¯5æ¥éã®ã¿ä¿åããããã®åŸäžèŠã«åé€ãããŸããããã¯ãã¯ã©ãŠã³ã§å®è¡ãããçããŒã¿ãåŠçããããããããã³ã³ãã¯ããªèšç®ããã圢åŒã§æ¢ã«ä»ã®ã³ã¬ã¯ã·ã§ã³ã«æžã蟌ãã¹ã¯ãªããã¢ã°ãªã²ãŒã¿ãŒãååšããããã§ãã
ã¬ããŒãäœæ
æåã«ãã¬ããŒãã¯findïŒïŒããã³
Map-Reduceã䜿çšããŠäœæãããŸããã collection.findïŒïŒã¡ãœããã¯åçŽãªéžæã«äœ¿çšãããããè€éãªãã®ã¯Map-Reduceã䜿çšããŠæ§ç¯ãããŸããã 2çªç®ã®æ¹æ³ã¯æãè€éã§ãåæ£ã³ã³ãã¥ãŒãã£ã³ã°ã¡ã«ããºã ãšå®éã®çµéšãå®å
šã«ç解ããå¿
èŠããããŸãã MySQLã§AVGãSUMãORDER BYæŒç®åã«ãã£ãŠè§£æ±ºãããã¿ã¹ã¯ã¯ãçµæãååŸããããã«Map-Reduceã§ç¹å®ã®ããªãã¯ãå¿
èŠãšããŸããã ãã®ãšãã®è¯ãèŽãç©ã¯ãMongoDB 2.2ã®å®å®ããŒãžã§ã³ã®ãªãªãŒã¹ã§ãããAggregationFrameworkãç»å ŽããããŒã¿ããŒã¹ããè€éãªãµã³ãã«ãéåžžã«ç°¡åãã€è¿
éã«äœæã§ããŸãããMap-Reduceã«ã¯é ŒããŸããã§ããã
éçŽã«ãããªã¯ãšã¹ãã®äŸïŒIDãããªã§ããŒã¿ãã°ã«ãŒãåããèŠçŽ|ã€ã³ãžã±ãŒã¿ãŒã§å¹³åãååŸïŒïŒ
db.stat20141103.aggregate([ { $match : { $nor : [{ ap : {$gt: 20}, loaded :0 }]} } , { $group: { _id:"$video_id", sum:{$sum:1}, active:{$sum:"$active" }, passive:{$sum:"$passive" }, buffer:{$sum:"$buffer" }, rewind:{$avg:"$rewindn" }, played:{$sum:"$played" } } } ]);
å±éãšãããã°
ããããã¹ãŠãé«è² è·äžã§é©åã«æ©èœããããã«ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãšããŒã¿ããŒã¹ãå°ãæ§æããå¿
èŠããããŸãã
- OSèªäœã§ã¯ãèšè¿°åã®æ°ãå¢ããå¿
èŠããããŸããã Ubuntuã®å Žåãããã¯æ¬¡ã®ãšããã§ãã
ä»ã®Linuxã·ã¹ãã ã§ã¯ã/ etc / sysctl.confãã¡ã€ã«ã®èšå®ã
- MongoDBãé«éåããããã«ãããŒã¿ããŒã¹ãã¡ã€ã«ã¯SSDã«é
眮ãããŸããã ãŸããããŒã¿ããŒã¹æ§æãä¿®æ£ããå¿
èŠããããŸããïŒãžã£ãŒããªã³ããªãã«ããŠããã£ã¹ã¯ã®ãã©ãã·ã¥ãšæ
å ±ã®æéãæäœããŸããïŒstorage.syncPeriodSecs-ãã®ãã©ã¡ãŒã¿ãŒã¯ãMongoDBãRAMãããã£ã¹ã¯ã«ããŒã¿ãã¢ã³ããŒãããé »åºŠã瀺ããŸãïŒã
/etc/mongodb.conf journal: enabled: false
PSã³ã¡ã³ãã®è³ªåãžã®åçã§èšäºãè£è¶³ããããšã«ããŸããïŒ
MongoDBããŒã¹ãéžæããçç±ã¯äœã§ããïŒ
MongoDBããŒã¿ããŒã¹ã®éžæã¯ãããã䜿ã£ãäœæ¥ã§æ¢ã«è¯å®çãªçµéšããã£ããšããäºå®ã«ãããã®ã§ãããPostgreSQLã¯ãã®ã¿ã¹ã¯ãåŠçã§ãããšæããŸã-ããè¯ãçµæãåŸãããå¯èœæ§ããããŸã
PIDã¯ã©ã®ããã«ãã©ãã§çæãããŸãããïŒ
PID-äžæã®ãã£ãŒã«ããäžæã®ãã¥ãŒãèå¥ããå¿
èŠããããŸãã äžæã®ãŠãŒã¶ãŒIDïŒIPããã³ãã®ä»ã®æ
å ±ã«åºã¥ããŠçæãããŸãïŒ+çŸåšã®Unixã©ãã«ãUAgentãç»é¢è§£å床ãããã³ã©ã³ãã å€æ°ã«åºã¥ããŠçæãããŸãã
圌ãã¯ããŒãžãéããPIDãäœæãããããã«åãããŒãžãæŽæ°ããŸããããŸã£ããç°ãªãPIDããããŸãã
ãŠãŒã¶ãŒããŒãžã®JavaScriptã§çæãããäžæã®ãŠãŒã¶ãŒIDã¯ãCookieãä»ããŠãµãŒããŒããååŸãããŸãã
ãžã£ãŒããªã³ã°ã¯æå¹ã«ãªã£ãŠããŸããïŒ ããã¯ã¢ãããèé害æ§ïŒ ãããŠãããŒãã¬ãã«ã§ã®ãã©ãŒã«ããã¬ã©ã³ã¹ïŒ
ãžã£ãŒãã«-ãªã-æ°åã§ãããã®çµ±èšããã®ããŒã¿ã®æ倱ã¯ããã®ãããžã§ã¯ãã«ãšã£ãŠéèŠã§ã¯ãããŸãã
ãã©ãŒã«ããã¬ã©ã³ã¹ããŒã-䜿çšããå Žåãåã¹ããªãŒã ã®è»œåŸ®ãªãšã©ãŒããã®ã¹ããªãŒã ãåæ¢ããããããã¹ããªãŒã ã®å Žåã¯WebãµãŒããŒå
šäœãåæ¢ãããããšãããããŸãã
ãããã¹ããªãŒã ã§æ¬¡ã®ããã«æ±ºå®ããŸãããåšã®æµããç£èŠããã転åããå Žåã¯åéãããŸããã
ãããã¹ããªãŒã ãäœäžããå Žåãæ°žä¹
ã«äœ¿çšãããŸãã-ãµãŒããŒãã¯ã©ãã·ã¥ããå Žåãããã«åèµ·åãããšã©ãŒããã°ã«æžã蟌ãŸããŸãã
ã¬ããŒãåä¿¡ã®éåžžã®é
延ãšã¯äœã§ããïŒ æçµæ¥ã®éèšãŸãã¯å¯èœãªéããªã¢ã«ã¿ã€ã ã«è¿ãïŒ
å
éšçµ±èšãããã圌女ã¯ãã©ãã£ãã¯ã«é¢ããããã€ãã®åºæ¬çãªããšãæžããŠããããªã¢ã«ã¿ã€ã ã§å©çšã§ããŸããèšäºã§èª¬æãããã®ã¯1æéã®ééã§éçŽãããŠããŸã-ããã§ååã§ã
åãGoogleã¢ããªãã£ã¯ã¹ïŒãŸãã¯YandexMetricaïŒã§æºè¶³ããªãã£ããã®ã¯äœã§ããïŒ ããªããæžãããã®ããããã¹ãŠãããã§ã§ããŸã
å€ãã®ãã©ãã£ãã¯ãã°ãŒã°ã«ãªã©ããµã³ããªã³ã°ã䜿çšããŠã¬ããŒããäœæãããµãŒãã¹ã®è² è·ãæžããããã«äŸé ŒããæçŽãå±ããŸãã
Apache Storm-Hadoop / Sparkããã®ã¯ã©ã¹ã®ã¿ã¹ã¯ã®æšæºã§ã¯ãªãã®ã¯ãªãã§ããïŒ
Apache Storm / Hadoop / Sparkã¯ãããã«ç²ŸéããŠããªããããJAVAã§èšè¿°ããŸãã
æåã¯ãphp / MySQL / JS / HTMLã§ããŸããŸãªã³ãŒããæžãçµéšãè±å¯ã§ããã
nodeJSã§ã¯ãJSæ§æãã»ãšãã©ã®éšåã§ãããããéžæã¯åœŒå¥³ã®æ¹åã«èœã¡ãŸããã
ãŸããããã§ã®è°è«äžã«ãèå³æ·±ãã¢ã€ãã¢ãæµ®äžããŸãã-NodeJSã®äžéšãnginxã«çœ®ãæããå¿
èŠãªåœ¢åŒã§ãã¹ãŠã®ããŒã¿ããã°ã«æžã蟌ã¿ãäžéšã®ã¢ããªã±ãŒã·ã§ã³ã¯æ¿å
¥æã«ãã®ãã°ãèªã¿åããããŒã¿ãåŠçããŠããŒã¿ããŒã¹ã«æ¿å
¥ããŸãã ã¿ã¹ã¯ã®çŸåšã®ç¶æ³ã§ã¯ããããããŸãå®è£
ã§ããŸã-ãã®ãªãã·ã§ã³ã®äž»ãªè°è«ïŒnginxã¯ãé·å¹Žã«ããã£ãŠéåžžã«ä¿¡é Œæ§ãé«ãå®çžŸã®ãããœãªã¥ãŒã·ã§ã³ã§ãã