最近我司须要作一个统一的游戏日志系统,要求有必定的通用性,能应对公司全部的游戏业务。接下来分享一下此次日志系统的项目经验。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个:
参考文献:
注:本文首次发布与简书