XinyiZhou xinyizhou@pptv.com 11/5 2012 PPTV LB日志实时分析平台 XinyiZhou xinyizhou@pptv.com 11/5 2012
Agenda PPTV LB日志实时分析系统介绍 系统实现 应用实例 实际面临的问题 解决方案 系统部署 Fluentd(td-agent) MongoDB Python Script(PyMongo module) Zabbix 应用实例 Nginx return code 4xx 5xx 监控 Nginx响应时间监控 告警邮件自动分析程序 LB日志实时分析与自动Release平台的集成
实际面临的问题 PPTV采用Nginx+Keepalived的方式构建Load Balancer,共有约40台LB server,每台承载10-50个域名的流量,我们需要精确的把握所有域名的健康状态(返回码是否正常,4xx/5xx率),及响应时间变化趋势;能够准实时的发现入侵行为; 难点: 日志量大 – 每台LB每天都有几百GB日志(压缩前) 日志分散不易进行统一分析 难以添加有效监控
解决方案(一) awk+grep+bash+gnuplot 最方便的一招,比较灵活,计算准确;但实际使用不方便,看一个域名的日志需要登陆好几台LB E.g. 统计非200的top return code awk '{if ($9 ~ /^[0-9]*$/ && $9 != "200" && $9 !~ /^3/) code[$9]++}END {for ( i in code ) print i " " code[i]}'|sort -k2 –nr 使用gnuplot对统计结果绘图 cut –d’’ –f1-4 log.txt | uniq –c | (echo “plot “-” using 2:1 with lines”;cat)|gnuplot
解决方案(二) Python+zabbix 每台LB均部署python日志分析脚本,通过zabbix调度,每隔五分钟对前五分钟生产的日志文件进行分析,保留分析结果; Zabbix负责绘图和告警; 主要两个缺点: 1)性能瓶颈,日志分析占用大量LB CPU资源 2)不够灵活,日志分析局限于单台LB
解决方案(三) Fluentd+Mongodb+Python+zabbix Fluentd实时收集LB日志,JSON化,存入中央Mongodb Python程序查询Mongodb数据进行实时计算;计算结果存入zabbix;zabbix负责告警及图形展现 P.S. That’s what we want!!
Fluentd/Mongodb架构图
Fluentd介绍 开源日志收集工具 http://fluentd.org/ LOG everything as JSON! JSON:Schema-free, add/remove field from logs at anytime 原始日志: “2012-10-01 host1 myapp: message size=1000 user=xyz” JSON: 2012-10-01 myapp.message { “hostname”: ”host1”, “size”: 1000, “user”: “xyz” }
Fluentd/Mongodb数据流图
Fluentd plugin说明(1) 在不使用plugin的情况下Fluentd仅仅是将日志输入转化为JSON格式输出的工具;各类plugin极大拓展了Fluentd的功能 Fluentd plugin有如下三种: Input plugin 定义日志来源标准化,输入的格式 Buffer plugin 定义fluentd缓存的配置以实现可靠性 Output Plugin 定义输出的格式及目的地,可以是文件,网络,数据库,etc
Fluentd plugin说明(2) Fluentd Input Plugin http tail foward exec 让fluentd从http client获取数据 tail tail是最常用的input plugin; <source> type tail path /var/log/httpd-access.log #tail监听的文件地址 tag apache.access #每个输入需要一个特定标签以区别 format apache|syslog|自定义正则 #format可以灵活自定义 </source> foward 将其他fluentd/fluent-cat命令的输出作为该fluentd的输入; exec 通过执行外部命令,以命令执行的结果作为fluentd的输入;
Fluentd plugin说明(3) Fluentd Output Plugin Ouput Plugin用于存储Fluentd收集来的数据;目前有很多开源的plugin,如:fluentd-flume,fluentd-splunk,fluentd-cassandra,fluentd-scribe,fluentd-mongodb fluent-plugin-mongo 0.6.10 Output plugin中最完美的当属mongodb plugin,因为Fluentd/Mongodb都以JSON为基础;mongodb良好的插入查询性能可以顶住海量日志实时分析的压力;mongodb的capped collection很好的解决了日志定量轮转的问题
MONGODB部署 每个机房部署一台mongodb server,用于收集该机房全部LB的日志 每个mongodb部署多个instance,每个instance对应一台LB server 建立多个collection,每个collection保存一个域名的日志信息 一定要使用capped collection!
MONGODB配置 port = 270XX dbpath = /home/mongodb/node270xx logpath = /home/mongodb/node270xx.log syncdelay = 10 #这个设置10秒左右,将IO压力平均化,避免sync时影响查询性能 maxConns = 20000 oplogSize = 1024 directoryperdb = on logappend = on journal = off fork = on nohttpinterface = on
Fluentd部署 每台LB上均需安装一个Fluentd agent;使用TreasureData公司yum源上提供的td-agent rpm包安装即可; 启动方法 /etc/init.d/td-agent start 关键配置/etc/td-agent/td-agent.conf 日志文件 /var/log/td-agent/td-agent.log
PPTV Fluentd Input配置 <source> type tail path /home/logs/nginx/aplus-access.log pos_file /var/log/td-agent/tmp/aplus.pptv.com.pos format /^(?<ip>[^ ]*) (?<domain>[^ ]*) - ([^ ]*) ([^ ]*) "(?<url>[^"]*)" (?<code>[^ ]*) (?<bsize>[^ ]*) ("[^"]*") ("[^"]*") ("[^"]*") "(?<restime>[^"]*)" "(?<backend>[^,"]*)[^"]*" "(?<bcode>[^,"]*)[^"]*" "(?<nginxtime>[^"]*)"$/ tag mongo.aplus.pptv.com.access </source>
PPTV Fluentd Output配置 <match mongo.aplus.pptv.com.access> type mongo database LB_hostname collection aplus.pptv.com.access host mongodb_host port mongodb_port capped capped_size 180m #确保能够保留最近1小时该域名的日志 ignore_invalid_record true buffer_type memory #使用内存作为buffer存储方式 buffer_chunk_limit 1M buffer_queue_limit 15 retry_limit 10 retry_wait 1s flush_interval 1s #刷新频率为1s,基本做到实时 </match>
PPTV日志样例 原始日志: 218.26.242.14 999.fb.app.aplus.pptv.com - [05/Nov/2012:15:42:38 +0800] "GET /recommend_pop/?_=1352101423806 HTTP/1.0" 200 34 "http://v.pptv.com/show/MLibyMJjibbqyJB28.html" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)" "60.211.95.201, 127.0.0.1" "0.012" "10.201.10.94:80" "200" "0.012“ MONGODB中的日志: { "_id" : ObjectId("5097755c31d87b09f8046f1f"), "ip" : " 218.26.242.14", "domain" : "999.fb.app.aplus.pptv.com", "url" : " GET /recommend_pop/?_=1352101423806 HTTP/1.0", “code” : “200”, #返回码 "bsize" : “34", #bodysize “restime” : “0.012”, #后端服务响应时间 “backend” : “10.201.10.94:80”, #后端服务地址 “bcode” : “200”, #后端服务返回码 “nginxtime” : “0.012”, #nginx响应时间 "time" : ISODate("2012-11-05T15:42:38Z") }
PPTV LB日志分析逻辑(1) 为LB日志自动生成fluentd配置文件: 对某台/log/nginx/*.access.log和*.error.log: 根据LB所在机房分配后端mongodb地址/端口,根据历史日志大小分配capped collection size,根据LB机器名分配mongodb database_name,根据域名确定mongodb collection name.
PPTV LB日志分析逻辑(2) 保存域名-LB-后端主机的对应关系,并定期更新(parse nginx配置文件) > db.domain_host_info.find({domain:"aplus.pptv.com"}) { "_id" : ObjectId("5096bc7b19859831d6000002"), "domain" : "aplus.pptv.com", "host" : “lb1", "backend" : “host1" } { "_id" : ObjectId("5096bc7b19859831d6000003"), "domain" : "aplus.pptv.com", "host" : " lb1", "backend" : “host2" } { "_id" : ObjectId("5096bc7b19859831d6000004"), "domain" : "aplus.pptv.com", "host" : “lb2", "backend" : “host3" } { "_id" : ObjectId("5096bc7b19859831d6000005"), "domain" : "aplus.pptv.com", "host" : “lb2", "backend" : “host4" }
PPTV LB日志分析逻辑(3) 每五分钟对前五分钟mongodb收集到的日志基于域名进行汇总计算(python/pymongo),得出结果存入mongodb中的lb_detail表: > db.lb_detail.findOne() { "_id" : ObjectId("509434522573b0625d000002"), “domain” : “xxxxx.pptv.com”, #分析的域名 “ng1_count” : 0, #nginx请求时间超过1秒个数 “be1_count” : 0, #backend后端响应时间超过1秒个数 “total_count” : 2703, # 过去5分钟该域名的请求总数 “backtime_total” : 6.71, # backend后端响应时间总和 “bodysize_total” : 124100, #bodysize总和 “xx4_count” : 2, #4xx请求个数 "time" : ISODate("2012-11-03T05:00:02.634Z"), “ng3_count” : 0, #nginx请求总时间大于3秒的请求个数 “c200_count” : 2700, #200请求个数 “xx5_count” : 1, #5xx请求个数 “ngxtime_total” : 7.191, #nginx请求总时间 “be3_count” : 0 #backend响应时间超过3秒的个数 }
PPTV LB日志分析逻辑(4) 每五分钟对前五分钟mongodb收集到的日志基于后端机器进行汇总计算(python/pymongo),得出结果存入mongodb中的backend_detail表: > #某域名xxxx.pptv.com中某后端机器(backend_ip:80)过去5分钟的4xx/5xx/响应时间/超时次数情况 > db.backend_detail.findOne() { "_id" : ObjectId("509677552573b02445000004"), "bk_xx5_count" : 183, "bk_be3_count" : 62, "bk_ng3_count" : 65, "bk_body_size_total" : 214842812, "bk_ngx_time_total" : 1443.1720000000564, "bk_be1_count" : 83, "domain" : “xxxx.pptv.com", "bk_total" : 25378, "server" : “LB_NAME", "bk_back_time_total" : 1233.362000000008, "bk_c200_count" : 25140, "time" : ISODate("2012-11-04T22:10:29.004Z"), "bk_xx4_count" : 42, "bk_ng1_count" : 109, "backend" : “backend_ip:80" }
PPTV LB日志分析逻辑(5) 对前面(3),(4)实时分析得出的结果,配置zabbix监控项进行采集、绘图 Zabbix监控脚本使用python/pymongo查询mongodb中lb_detail/backend_detail表获取过去5分钟 某域名的总请求数/2xx率/4xx率/5xx率/平均响应时间/后端响应超过1秒的比率等
Zabbix监控(1) 建立zabbix LB_log_mining监控模板,对每个域名建立总请求数,4xx/5xx数,后端平均响应时间,nginx响应时间,bodysize平均大小,响应时间>1秒比例,响应时间>3秒比例 (每五分钟采集一次)
Zabbix监控(2)
Zabbix监控(3) 如上页所示,某域名的总请求数、4xx、5xx比率,平均响应时间,均可以在zabbix中查看变化趋势;针对4xx、5xx率特别高或者响应时间>3秒的比率特别高的,可以进行实时告警; 告警邮件见下图;
Zabbix监控(4) Zabbix告警邮件实例;
The End