解答一个关于日志系统的思路
在一个群里看到一个面试题,试着去解答一下,毕竟正好花时间了解过日志这方面的内容。 希望能达到的使用场景: 在写业务逻辑时也能进行结构化的log, 并且log被转移到一个数据库, 一个UI前端以这个log数据库为支持, 可以可视化各种指标, 并且保留未来可以对指标进行alarm的可能性 希望从两个方面考虑这个问题: 技术通路实现。 在每一步会用些什么技术? 一些核心组件比如log采集和log数据库有哪些已有方案, 是否有优劣? 从运维角度看, 这套系统可能在哪些方面有需要考量的地方。 比如log采集是否会影响业务进程? log数据库的运维可能遇到哪些问题? 可以看出问题提出者比较在意解决这些问题过程中的思维方式和学习能力,弱化实践经验的要求。 首先根据要求确认一下要达到效果: log日志采集 log存储 log展示 alarm报警(附加) 1 确定日志流向/架构 因为一开始脑海里也不知道原型是怎样的,就是以前用过linux自带的rsyslog功能感觉很类似:在日志服务器上通过配置rsyslog存入mysql的插件,而其它的各个服务器上默认rsyslog都是开启的,修改conf的系统日志、mail、cron等不输出到本地,而是指向mysql数据库。前端通过loganalyzer从数据库获取数据,图形化显示(简陋到不想说了。。。),但是显示的柱形图/饼图没有什么意义,默认对系统messages处理比较方便,要记录nginx或业务逻辑的log还需做其它额外操作。 但rsyslog并不是一无是处,它的整个架构特别是消息队列的设计,跟后面要讲的许多分布式日志系统是很像的。所以脑海里日记采集的原型出来了: 业务逻辑的日志输出到文件file,服务上的日志采集客户端agent实时监控这个logfile,作为输入;日志中心服务器server接受来自agent的消息,存入后端数据库。另有一个UI从这个数据库取得数据显示,并提供搜索、统计图表。 然而有以下几个问题需要考虑,这也就是为什么出现各种开源解决方案: 日志产生数量过大,不能及时发送到server怎么办 可以使用队列或redis来缓冲 日志中心服务器server故障怎么办,肯定不能丢失日志,即可靠性 有的解决办法是对 log server 做集群,通过zookeeper来同步配置;有的是在agent上本地暂时存放,等恢复后重新传输,redis就可以承担这个角色 考虑到这个日志平台的可扩展性,新的日志来源input不一定是file,比如rsyslog 至少需要支持常用的input 是否支持过滤功能 filter可以在日志发送之前就把不匹配的日志内容排除掉 log结构化 收集的日志初始是一长字符串,为了后面使用方便,需要将日志结构化存储(后面会有说明) 存储采用关系型数据库对海量日志存储,性能肯定很大问题 log日志存储没有一致性的要求,甚至可以说一条日志根本就没意义,而是需要通过大量的日志,通过分析、比较趋势具备用处。于是日志的存储各显大招,主流有两种:hadoop分布式文件系统HDFS,elasticsearch(后面简称es)全文搜索引擎,它们都具备很强的可伸缩性和多节点高可用性 由于存储方式的不同,数据分析与展示也就有各自的阵营 HDFS一般采用MapReduce处理数据,es既可以通过其丰富的插件显示或搜索数据,也可以通过推荐使用的kibana来展示数据 总结下来大致流程图如下: 2 log结构化 当然可能你一直存在这样一个疑问:log的结构化问题处理 代码里logger的内容大概是timestamp,log_level,module,message… ,一下是nginx的access示例: 172.16.30.88 - [08/Jun/2015:00:08:38 +0800] "POST /notice/statement_findStatementVByPage.htm?1433637553824 HTTP/1.1" 200 114 "http://service.tp-link.net/" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)" 处理这条非结构话的字符串或消息,无非就是在它发送到日志中心之前格式化,像最简单的rsyslog处理方法是通过数据库表字段Mapping来存放,而es则是通过编写Grok规则来结构化,如将IP、日期、请求方式、响应状态码、响应时间等组合成json字符串。(然而Grok写起来是非常痛苦的,以至于官方github上专门维护了一份通用规则表)...