最近我司須要作一個統一的遊戲日誌系統,要求有必定的通用性,能應對公司全部的遊戲業務。接下來分享一下此次日誌系統的項目經驗。node
目前流行的日誌系統爲ELK,由Beats、Logstash、Elasticsearch、Kibana等組件共同實現,但萬變不離其宗,一個基本的日誌系統架構相似以下:redis
遊戲分析,與其它服務系統不一樣的是,遊戲內的系統多是天馬行空的,數據類型是多樣的,甚至頻繁變化的。咱們要在變化中總結到不變的內容,例如系統經濟產出,玩家物品消耗,商店購買等進行分析。因此此次的遊戲日誌系統要知足如下需求:express
雖然ELK在安裝配置方面不算困難,插件衆多,例如Filebeat,讀log文件,過濾格式,轉發,但誰來生產這些log文件,沒有說起。實際上,業務具備多樣性,只要有日誌文件的地方,它就能夠用。例如多數會使用Nginx進行日誌收集。咱們也須要考慮到日誌生產者的問題,責權分離,須要單獨一臺機子進行日誌採集。緩存
遊戲是一種技術與藝術結合的產品,數據龐雜,形態萬千,光日誌埋點也花很多功夫,但不能所以放棄治療。好的遊戲日誌,還能夠幫咱們還原玩家玩家畫像。遊戲更新週期短,數據變化大,須要提供更實時參照報表,爲非技術人員更好友的查詢界面,才能更好的服務於遊戲數據分析。ELK 在這方面,基本解決了採集和儲存的問題,但實現分析方面還不能知足咱們的需求。安全
通過一翻思索,咱們能夠用現有工具,粘合多個套件,因此,咱們有了如下思路:服務器
利用Fluented做爲日誌文件採集器,生產者經過內網HTTP發送到採集器上,那每一個生產者同一內網只要部署一個採集器便可,若是量特別大,能夠多個,遊戲的功能埋點能夠統一;markdown
利用NodeJS進行 HTTP 轉發便可,前提是能按順序和分段讀取日誌文件,結合Fluented間接實現;網絡
接收器能夠用Koa實現,Redis進行緩存;同時用NodeJS另一個進程分析和日誌入庫,分析行爲,玩家畫像,得出報表,這些非日誌源的數據,能夠放到MongoDB上,由於這些數據是修改性增加緩慢數據,佔用空間不大;數據結構
ElasticSearch是個很好的選擇,能集羣,可熱增減節點,擴容,還能夠全文檢索,分詞;架構
Kibana針對 ElasticSearch提供良好的分析,結合原有的管理後臺系統,咱們本身實現了一套用戶界面。
這個框架主要使用到了Fluentd,ElasticSearch,以及NodeJS,我就稱它爲 FEN 架構吧,以下圖。
上圖看出,這樣的日誌架構和第一個圖基本沒什麼不一樣,只是多了後面的分析與分批入庫處理,而且大量使用了NodeJS。
注:在這裏不會介紹各組件的詳細的安裝配置方法,網上有太多了,怎樣使用好每個組件纔是關鍵。
先介紹咱們用到的工具:
Fluentd是一個徹底開源免費的log信息收集軟件,支持超過125個系統的log信息收集。Fluentd在收集源日誌方面很是方便並且高性能,經過HTTP GET就能夠,這相似於Nginx的日誌記錄行爲。它的優勢是,日誌文件能夠高度定製化,例如咱們這裏每5秒生成一個文件,這樣每分鐘有12個文件,每一個文件體積很是小。爲何要這樣作?下面會介紹。Fluentd還有很是多的插件,例如直接存入MongoDB,亞馬遜雲等,要是熟悉Ruby,也能夠本身寫插件。
有人使用MongoDB進行日誌收集,是很是不明智的,只有幾千萬條還能夠,若是半個月生產10億條日誌呢?日誌文件須要保存一個月甚至更長,那麼集羣和硬盤維護就很是重要。使用便利性也很重要,例如分詞檢索,在客服回溯玩家日誌,分析遊戲 BUG 的時候很是有用。下文的 ES 也是該組件的簡稱。
NodeJS不適合作 CPU 密集型任務,但在網絡應用方面還不錯,而且是咱們正好熟悉的。日誌系統對實時性要求並不高,延時半小時之內都是容許的,事實上,正常狀況延時也就10來秒。下面的讀與轉發日誌的Pusher,收集日誌的logger,分析日誌並數據落袋爲安的的analyser,都是由NodeJS實現的。
下面繼續介紹用 NodeJS實現的每個部分:
(注:這是一個nodeJS編寫的服務。) 上面說到,爲何Fluentd使用分割成多個小文件的方式,由於NodeJS在大文件處理方面並不友好,而且要考慮到經過網絡發送到另外一臺機,轉發速度比讀慢太多了,因此必須實現續傳與斷點記錄功能。想一想,若是讀幾百 M 的文件,出現中斷後,須要永久記錄上次位置,下次再今後處讀起,這就增長了程序複雜度。NodeJS雖然有readline模塊,但測過發現並不如文件流那樣可控,訪模塊用於交互界面尚可。相反,若是日誌分割成多個小文件,則讀的速度很是高效,而且每5秒一個文件,哪怕有上萬條記錄,文件也大不到哪裏去,內存也不會佔用太多,在斷點續傳與出錯重試方面都能自如應對。若是遊戲日誌增多,能夠增長節點來緩解文件過大的壓力。
爲何不直接讓日誌生產者直接發到Koa上?由於效率與帶寬。NodeJS的適合作網站,但比專業的HTTP服務器要弱太多,4核心主機面對3000QPS就吃力,更多的關於NodeJS的性能問題,能夠參考網絡文章。在高併發量下,帶寬是個很大的問題,尤爲是須要作統一服務,面對的狀況是日誌機器與遊戲並不在同一內網中。在10萬日活下,帶寬超過了50M,很是嚇人,帶寬但是很貴的,太高的帶寬費用在這裏性價比過低了。
這裏咱們使用Koa做爲日誌採集器。使用Koa,不管在性能仍是開發效率上,都比expressJS高效。咱們還用到了Redis做爲緩存,而不是直接在這裏作分析任務,是爲了儘可能提升與Pusher的對接效率,畢竟日誌的生產速度是很快的,但網絡傳送是相對低效的。
注:pm2 3.2.2的集羣可能出現集羣內端口衝突的弔詭問題,建議用3.0.3或最新版本
(注:這也是一個nodeJS編寫的服務。) 分析器讀取Redis的內容,這裏就是單進程的隊列操做。到這一步,日誌怎麼分析,就能夠很自由了。
由於咱們自己有後臺管理系統,因此咱們很方便的把用戶畫像與其它分析點接了入去,在查詢玩家行爲時,咱們搜索ES,在查詢分析報表時,咱們查詢MongoDB中的數據。固然咱們也使用了Kibana來知足可能的需求。
目前該日誌系統運行1個半月,由純MongoDB到結合 ES,走了很多彎路,還好如今終於穩定下來。目前在性能方面,logger 與 analyser都在同一臺機,平均 CPU 爲23%左右,高峯47%左右,說明還有更大的機器壓榨空間。
內存方面,在高峯期5G 之內,整體很是平穩沒多大波動,其中redis內存使用爲800MB之內,但機器是16G,還有很大餘量保障。
NodeJS 的腳本中,logger的CPU佔用更小,3條進程,每條才3%,每條內存佔用不到100MB。analyser 的 CPU 與內存佔用多一點,這一點能夠經過腳本內的參數調整,例如內存計數的內容清理得更快,使用pm2的話設置max_memory_restart : '4G' 均可以提升穩定性。
以上是我在遊戲日誌系統中的經驗總結。
以上方式,是【本地文件收集】-【推送到】-【分析】-【入庫與分析結果保存】,萬一須要對已經入庫的數據從新分析呢?例如之前有個數據運營漏了放到需求裏,須要對某個時期的日誌從新分析。
解決思路有2個:
參考文獻:
注:本文首次發佈與簡書