最近做了一個打點統(tǒng)計系統(tǒng),統(tǒng)計系統(tǒng)肯定各個公司都有做過,至于怎么做就不好說了。我見過最多的就是使用php開發(fā)一個打點接口,然后在打點接口中做數(shù)據(jù)點擊,這種方法最差的就是每次打點都往數(shù)據(jù)庫中操作,另外一種就是往一個文件中增加數(shù)據(jù)。對于后一種,我就很奇怪了,你既然php是等于要往日志文件中增加一條記錄,那干啥不用web服務器的自身的日志呢?所以我這次就果斷使用分析nginx日志的方法來做打點(這個方法也是大多公司統(tǒng)計系統(tǒng)采用的方法吧)。
nginx日志打點第一個使用什么打點接口,當然可以自己放一個文件在服務器,然后訪問這個文件。但是實際上nginx有個empty_gif的模塊,它把圖片存放在nginx的內(nèi)存中,所以它的訪問速度比靜態(tài)文件的訪問速度還快,所以果斷選擇這個。因此我的配置文件如下: server { listen 80; server_name ares.; access_log /home/web/ares/log/ares..access.log; access_log /home/web/ares/log/ares..static.log; error_log /home/web/ares/log/ares..error.log notice; root /home/web/test/www/; index index.php; location = /ares.gif { empty_gif; } } 這里我把access_log寫兩份,目的是希望我一份做存留,一份做分析。 我設(shè)計的訪問接口是http://ares./ares.gif?p=a&i=b 這里的p和i是統(tǒng)計的項目和統(tǒng)計項。
然后日志寫完了之后,就需要進行日志切割了,日志切割怎么搞都行,我就搬起了php最快上搞,就是這里要注意下切割完日志以后要給nginx發(fā)送一個信號,讓它修改下日志的fd。 @rename($srcLog, $disLog); // 發(fā)送信號給nginx $pidFile = Yii::app()->params->nginxPid; $command = "kill -USR1 `cat ${pidFile}`"; @system($command); 然后這個腳本我設(shè)置每1分鐘跑一次,將當前的日志用分鐘來重命名
下面就是分析日志的過程。 分析日志一定會是多個進程的環(huán)境。為什么,因為,一個進程,太慢。那多進程的環(huán)境,就需要有多個進程同時讀取一個文件的情況,分析日志的時候就需要注意下使用文件鎖。 $disLogs = glob(Yii::app()->params->logFolder . "ares_*.log"); foreach ($disLogs as $log) { $fp = fopen ($log , "rw+"); // 如果獲取到鎖 if (flock($fp , LOCK_EX)) { while(!feof($fp)) { $line = fgets($fp, 4096); // DO SOMETHING } ftruncate($fp, 0); fflush($fp); flock($fp, LOCK_UN); unlink($log); echo "logfile {$log} ok" . PHP_EOL; } fclose ($fp); } 然后這個腳本我會讓它循環(huán)跑10分鐘,每2分鐘啟動一個腳本,這樣就有5個腳本在跑。 至于數(shù)據(jù)庫設(shè)計,就和后臺需求有關(guān)了。 我這里第一版最簡單的就是記錄下每個小時的點擊數(shù)。 所以只需要最簡單的項目表,統(tǒng)計項表,統(tǒng)計數(shù)據(jù)表就好。 這樣子還有個好處就是可分布式擴展,如果一個統(tǒng)計前端機扛不住了,那么我就單純加機器就好了,反正這些數(shù)據(jù)都是往同一個數(shù)據(jù)庫中插入的。
至于后臺界面開發(fā),最近瘋狂喜歡上ACE這套后臺模板,然后畫圖使用HighChart來弄。 后臺統(tǒng)計項目如何加功能后面后面再說~
至此初步的統(tǒng)計就搞起來了。我在一臺機器上測試過前端壓力,8核的機器,大概能有1w左右的qps。至少能扛過一陣了。
|
|