最近做了一個打點統計系統,統計系統肯定各個公司都有做過,至於怎么做就不好說了。我見過最多的就是使用php開發一個打點接口,然后在打點接口中做數據點擊,這種方法最差的就是每次打點都往數據庫中操作,另外一種就是往一個文件中增加數據。對於后一種,我就很奇怪了,你既然php是等於要往日志文件中增加一條記錄,那干啥不用web服務器的自身的日志呢?所以我這次就果斷使用分析nginx日志的方法來做打點(這個方法也是大多公司統計系統采用的方法吧)。
至於storm,hadoop啥的,太高大上了。沒用
nginx日志打點第一個使用什么打點接口,當然可以自己放一個文件在服務器,然后訪問這個文件。但是實際上nginx有個empty_gif的模塊,它把圖片存放在nginx的內存中,所以它的訪問速度比靜態文件的訪問速度還快,所以果斷選擇這個。因此我的配置文件如下:
server { listen 80; server_name ares.test.com; access_log /home/web/ares/log/ares.test.com.access.log; access_log /home/web/ares/log/ares.test.com.static.log; error_log /home/web/ares/log/ares.test.com.error.log notice; root /home/web/test/www/; index index.php; location = /ares.gif { empty_gif; } }
這里我把access_log寫兩份,目的是希望我一份做存留,一份做分析。
我設計的訪問接口是http://ares.test.com/ares.gif?p=a&i=b
這里的p和i是統計的項目和統計項。
然后日志寫完了之后,就需要進行日志切割了,日志切割怎么搞都行,我就搬起了php最快上搞,就是這里要注意下切割完日志以后要給nginx發送一個信號,讓它修改下日志的fd。
@rename($srcLog, $disLog); // 發送信號給nginx $pidFile = Yii::app()->params->nginxPid; $command = "kill -USR1 `cat ${pidFile}`"; @system($command);
然后這個腳本我設置每1分鍾跑一次,將當前的日志用分鍾來重命名
下面就是分析日志的過程。
分析日志一定會是多個進程的環境。為什么,因為,一個進程,太慢。那多進程的環境,就需要有多個進程同時讀取一個文件的情況,分析日志的時候就需要注意下使用文件鎖。
$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); }
然后這個腳本我會讓它循環跑10分鍾,每2分鍾啟動一個腳本,這樣就有5個腳本在跑。
至於數據庫設計,就和后台需求有關了。
我這里第一版最簡單的就是記錄下每個小時的點擊數。
所以只需要最簡單的項目表,統計項表,統計數據表就好。
這樣子還有個好處就是可分布式擴展,如果一個統計前端機扛不住了,那么我就單純加機器就好了,反正這些數據都是往同一個數據庫中插入的。
至於后台界面開發,最近瘋狂喜歡上ACE這套后台模板,然后畫圖使用HighChart來弄。
后台統計項目如何加功能后面后面再說~

至此初步的統計就搞起來了。我在一台機器上測試過前端壓力,8核的機器,大概能有1w左右的qps。至少能扛過一陣了。
