接着上面一篇来说,这篇主要介绍logstash处理实时数据问题,日志数据更新时,logstash处理方式是默认每15s检查一次文件夹,每5秒检查一次文件,这些参数可以改变的。遇到当处理较多批次数据时,logstash出现卡死状态的原因,我目前猜测是输入文件较多logstash处理很快,而输出插件input elasticsearch这个插件线程限制,导致的死锁问题,后面详细说。最后展示一下kibana日志数据时区从UTC改成显示北京时间的几个方法,最后展示一下仪表盘效果。
先上logstsh中配置文件代码:
input {
file{
path => ["/home/cuixuange/Public/elk/test_log/*.log","/home/cuixuange/Public/elk/test_log/logs/*"]
start_position=>"beginning"
discover_interval => 15
stat_interval => 1
sincedb_write_interval => 15
}
}
filter{
grok{
match=>{ "message" => "(?m)%{DATA:timestamp} \[%{DATA:ip}\] . \[%{DATA:type}\] %{GREEDYDATA:log_json}"
}
}
json {
source => "log_json"
target => "log_json_content"
remove_field=>["logjson"]
}
# json {
# source => "trace"
# target => "trace_content"
# remove_field=>["trace"]
# }
date {
match => [ "timestamp", "yyyy-MM-dd HH:mm:ss" ]
locale => "en"
timezOne=>"+00:00"
}
}
output {
if[timestamp]=~/^\d{4}-\d{2}-\d{2}/{
elasticsearch {
host => "192.168.172.128"
index => "logstash-test-%{+yyyy.MM.dd}" #logstash-* to find
workers=>5
template_overwrite =>true
}
}
#stdout{codec=>json_lines}
}
简单解释解释意思:
1.
start_position=>"beginning"
logstash默认是ending,意味着每次重新打开logstash它不会从头加载文件,而是会从ending检查是否更新,毕竟实际中一般logstash实时性强,不会随意关闭的,而我们做实验就改成begining,否则不会发现文件内容的出现;
但是这样也就造成一个问题,多次重新打开logstash进行 -f 配置文件时,会造成数据重复读取,想elasticsearch再传一篇数据,es中搜索数据重复(亲测如此),比较繁琐的办法就是把elasticsearch索引删除,以前的数据就不会存在了
2.
discover_interval => 15
#设置多长时间扫描目录,发现新文件
stat_interval => 1
#设置多长时间检测文件是否修改
sincedb_write_interval => 15
#设置多长时间会写入读取的位置信息
3.
timezOne=>"+00:00"
elasticsearch原生支持date类型,json格式通过字符来表示date类型。所以在用json提交日期至elasticsearch的时候,es会隐式转换,把es认为是date类型的字符串直接转为date类型
也就是说es存储的时间是long存储的
更改ES 中显示@timestamp字段不是标准时间,小了8个小时原因,是因为我们读入的数据是北京时间转化为0时区存储再然后在kibana展示都是正确的。如果强行修改@timestamp,还需要在kibana上面修改。繁琐了
如果不行的话,可以采用下面的办法:
老版本(1.5之前的版本):
WithZone (org. Joda. Time. DateTimeZone: : UTC)
修改为:
WithZone (org. Joda. Time. DateTimeZone.getDefault ())
1.5以后的版本:
路径:/vendor/bundle/jruby/1.9/gems/logstash-core-(version)-java/lib/logstash/event.rb
我的例子(2.1版本的Logstash):
/logstash/vendor/bundle/jruby/1.9/gems/logstash-core-2.1.0-java/lib/logstash/timestamp.rb
57行
UTC = org.joda.time.DateTimeZone.forID(“UTC”)
修改为:
UTC = org.joda.time.DateTimeZone.getDefault(:)
4.
workers=>5
意即工作线程。Logstash 会运行多个线程。注意:Logstash目前还不支持输入插件的多线程。而输出插件的多线程需要在配置内部设置,这个命令行参数只是用来设置过滤插件的!提示:Logstash 目前不支持对过滤器线程的监测管理。如果 filterworker 挂掉,Logstash 会处于一个无 filter 的僵死状态。
提示:Logstash 目前不支持对过滤器线程的监测管理。如果 filterworker 挂掉,Logstash 会处于一个无 filter 的僵死状态。(我当时发现elasticsearch仅仅读入了一个文件)这种情况在使用 filter/ruby 自己写代码时非常需要注意,很容易碰上 NoMethodError: undefined method '*' for nil:NilClass 错误。需要妥善处理,提前判断。
所以说会出现文章开头的情况:下面是网上有几个的说法+我自己的猜测:
报错类似于:
[2014-02-07 16:11:36,681][WARN ][monitor.jvm ] [Warwolves] [gc][young][30][12] duration [1.1m], collections [11]/[3.1m], total [1.1m]/[1.1m], memory [485.9mb]->[1.9gb]/[15.9gb], all_pools {[young] [459.7mb]->[442.3mb]/[599mb]}{[survivor] [26.1mb]->[74.8mb]/[74.8mb]}{[old] [0b]->[1.4gb]/[15.2gb]}
[2014-02-07 16:11:47,451][WARN ][monitor.jvm ] [Warwolves] [gc][young][34][13] duration [7.4s], collections [1]/[7.7s], total [7.4s]/[1.2m], memory [2gb]->[1.6gb]/[15.9gb], all_pools {[young] [594.1mb]->[8.9mb]/[599mb]}{[survivor] [74.8mb]->[74.8mb]/[74.8mb]}{[old] [1.4gb]->[1.5gb]/[15.2gb]}
[2014-02-07 16:12:06,311][WARN ][monitor.jvm ] [Warwolves] [gc][young][41][15] duration [3.3s], collections [1]/[3.4s], total [3.3s]/[1.3m], memory [2.3gb]->[1.9gb]/[15.9gb], all_pools {[young] [562.1mb]->[8.5mb]/[599mb]}{[survivor] [74.8mb]->[74.8mb]/[74.8mb]}{[old] [1.7gb]->[1.8gb]/[15.2gb]}
[2014-02-07 16:16:52,440][WARN ][monitor.jvm ] [Warwolves] [gc][young][42][33] duration [2.2m], collections [18]/[4.7m], total [2.2m]/[3.5m], memory [1.9gb]->[4.1gb]/[15.9gb], all_pools {[young] [8.5mb]->[72.5mb]/[599mb]}{[survivor] [74.8mb]->[74.8mb]/[74.8mb]}{[old] [1.8gb]->[4gb]/[15.2gb]}
线程猜测:
input文件夹内部有较多文件,logstash input filter线程限制为1,不能更改output的输出到elasticsearch插件我的线程限制为5
待输入文件较多而每份文件却较小 ; 我猜测logstash进行grok解析后存储只同时只能向elasticsearch写5个文件(我自己写的配置文件限制为5),发生了死锁(似乎不满足死锁发生的4个条件,不过确实卡死了)
内存猜测:
elasticsearch是单节点的,而我用的1g内存的虚拟机,可能是内存不足而logstash没有预警处理(logstash不能检测内部几种插件线程处理的状态,不过在最新的几个版本kibana似乎可以进行检测了)(所以会存在一些数据库,比如说redis等nosql型作为日志数据的缓冲,防止一次性输入过多日志导致的崩溃,不过我们ELK还是更关注于实时数据,不太可能出现日志突然大量增加的情况)
插件本身问题猜测:
一些数据不是json型却被按照json格式解析,可能崩溃出错,也许自己编写的程序不够健壮;
解决:
单个文件不断手动加入更新,发现没有问题,全部显示,所以:内存不足的可能性排除、插件本身代码错误排除(不是json数据按照json插件进行处理还是有只不过会报错出来问题)
5.其它了解:
elastic数据无故丢失,分布式系统很难保证100%数据不丢失
解决方案:1.分布式系统的错误会服,比如说快照 2.数据备份
elasticsearch自动建立了mapping映射,例如:将@timestamp字段映射为date类型;将message字段映射为string类型等等
展示一下kibana最后简单弄了一张仪表盘的效果,挺简单的,不过还是觉得图样太少了....
附上当时解决问题的几个博客链接:
Logstash之时区问题的建议和修改
Logstash处理json格式日志文件的三种方法
Log4J & elk 事故总结,就是我上面说的logstash导入多文件时报错问题
同上
Logstash configuration配置语法