导入CDN日志到Elasticsearch
场景说明
需要临时分析CDN日志,最简单的是将CDN日志导到ELK集群中在Kibana 上进行分析,因为只是临时的分析,就在本地搭了一套ELK进行分析。
首先安装ES + Logstash + Kibana,这个不是重点,就不说了。
因为之前从来没有用过Logstash,在一顿查阅后开始做准备工作。
机器准备
节点 | 说明 | IP | 机器名 |
---|---|---|---|
Elasticsearch | Master | 192.168.1.20 | vm-es1 |
Elasticsearch | Master/Data | 192.168.1.21 | vm-es2 |
Elasticsearch | Master/Data | 192.168.1.22 | vm-es3 |
Logstash | 192.168.1.23 | vm-logstash |
上传文件
在安装Logstash的机器上
// shell
[root@vm-logstash]# cd /data
[root@vm-logstash]# mkdir cdnlog
上传日志文件到到cdnlog目录
Logstash配置
写logstash配置文件cdnlog.conf
input {
file {
type => "cdn_log"
path => ["/data/cdnlog/2019080610-web.abc.com"]
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
if [type] == "cdn_log" {
csv{
separator => " "
columns => ["logdate", "clientip", "host", "urlpath", "bodysize", "province","mno", "status", "referer","responsetime","useragent","range","method","protocol", "cache"]
}
date {
match => ["logdate", "yyyyMMddHHmmss"]
}
grok{
match => ["urlpath","%{URIPATH:uri_path}%{URIPARAM:uri_param}"]
}
mutate {
remove_field => ["urlpath"]
remove_field => ["range"]
}
}
}
output{
elasticsearch{
hosts=>["192.168.1.20:9200","192.168.1.21:9200","192.168.1.22:9200"]
index=>"cdnlog-%{+YYYY.MM.dd}"
manage_template => true
template => "/data/cdnlog/template.json"
template_overwrite => true
template_name => "cdnlog"
}
stdout{
codec => plain
}
}
input段
不记录当前位置
sincedb_path => "/dev/null"
即便start_position指定了beginning,如果没有这一行,logstash也会记录执行位置,中断后重新打开时也会从记录的位置开始读取数据。
文件名
如果一次只处理一个文件,可以直接写文件全名,如果处理一批文件也可以写通配符的形式
path => ["/data/cdnlog/2019080610-web.*"]
filter段
因为cdn日志本身就是以空格分隔字段的,符合csv格式,这里就直接使用了csv插件,当然也可以使用grok的方式匹配字段。
date插件
因为ES索引中增加了@timestamp字段,这个字段默认是插入索引的时间,为了让这个字段保存日志产生的时间,使用date插件重新匹配后,覆盖@timestamp字段,这个插件还有一个target属性,默认就是@timestamp,当然也可以指定其他字段。
如果日志时间使用的是格林威治时间,需要locale
和timezone
两个属性,如果日志里记录的就是本地时间,则不需要
date {
match => ["logdate", "yyyyMMddHHmmss"]
locale => "en"
timezone => "+00:00"
}
grok插件
grok插件是logstash中最强大的插件了,可以做很多的匹配工作,这里就不详细介绍了,这里的目的是分开urlpath字段中的path和urlparam两段存到uri_path和uri_param两个字段中。
mutate插件
日志中包含我们并不需要的字段,直接用remove_field去掉。
output段
elasticsearch 插件
主要是template属性和template_name属性,下一节介绍
stdout插件
把读取的内容输出到标准输出,能看到logstash正在努力的干活,在调试过程中使用,在真正运行中并没有太多用处。
如果有统计需求的话可以参考dots
插件
stdout{
codec => dots
}
Elasticsearch索引模板
上一节的output中的elasticsearch插件使用了索引模板,本来ES是有默认模板的,因为我们导入的数据字段会有我们要求的字段类型,默认模板全部使用string类型,所以我们要自己指定字段的数据类型,还有索引的其他设置。
编写ES模板文件template.json
{
"order": 10,
"version": 6100,
"index_patterns": ["cdnlog*"],
"settings": {
"index.number_of_shards": 2,
"number_of_replicas": 1,
"index.refresh_interval": "10s"
},
"mappings": {
"doc": {
"properties": {
"@timestamp": {
"type": "date"
},
"@version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"logdate": {
"type": "date",
"format": "yyyyMMddHHmmss"
},
"clientip": {
"type": "text"
},
"host": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"urlpath": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"bodysize": {
"type": "integer"
},
"status": {
"type": "integer"
},
"responsetime": {
"type": "integer"
}
}
}
}
}
order 属性
当我们要创建的索引匹配了多个模板时,settings和mpapings将会合成一个配置应用在这个索引上,order属性控制着合并的顺序,order值越大,优先级越高。
version属性
如果更新了模板文件,并不会自动应用,要更改version属性,让ES知道你这个模板有更新。
查看ES中的模板
#查看所有索引模板
[root@vm-es1]# curl -XGET http://192.168.1.20:9200/_template?pretty
#查看指定索引模板
[root@vm-es1]# curl -XGET http://192.168.1.20:9200/_template/cdnlog?pretty
执行logstash开始导入数据
[root@vm-logstash]# /usr/share/logstash --path.settings /etc/logstash -f es.conf -w 40
命令说明:
--path.settings 用于指定logstash的配置文件所在的目录,如果没有这个参数,配置文件在命令行模式时是不会被使用的
-f 指定需要被检测的配置文件的路径
-w 启动多少个工作线程
--config.test_and_exit 检测配置文件,检测完后就退出
效率优化
无论是logstash和elasticsearch如果都是默认启动,那效率是相当低的,有以下几点优化建议:
增加logstash应用内存
修改/etc/logstash/jvm.options文件
-Xms 1g
-Xmx 1g
改为4g,内存越大越好
-Xms 4g
-Xmx 4g
增加Elasticsearch应用内存
修改/etc/elasticsearch/jvm.options文件
-Xms 1g
-Xmx 1g
改为4g,内存越大越好,ES的内存有个32G现象,感兴趣的可以先自己搜一下
-Xms 4g
-Xmx 4g
增加logstash批处理条数
修改/etc/logstash/logstash.yml文件
pipeline.batch.size: 125
改为2000
pipeline.batch.size: 2000
增加logstash执行线程数
参考执行命令-w
参数,这个参与与批处理条数越大,占用的内存越大,ES接收数据也有一个上限,当达到上限时执行效率不会提高,甚至会出错,这个具体的数值,需要根据机器配置不断的尝试,我这里只是使用我的虚拟机设置的参数,也不一定是最优的。
增加Elasticsearch索引分片数
修改template.json文件中的index.number_of_shards
属性,分片数可设置为集群节点数量的2倍或3倍,集群超大的另说,当然,这个数据也是需要尝试的,不会越大越好。
减少Elasticsearch索引副本数
修改template.json文件中的number_of_replicas
属性,最快是0
,当然这样就失去了ES集群的容灾特性
增加Elasticsearch索引刷新时间间隔
修改template.json文件中的index.refresh_interval
属性,这个属性控制加入数据到可以被搜索到的时间,数据要被搜索到,需要这个刷新的操作,时间越长,开销越小,对于我们导入数据的场景来说,这个时间非常不重要,可以设置为1分钟或更长时间,甚至改为手动刷新。
遇到的问题
现象
执行一段时间后,logstash进程中断退出,显示killed。
排查问题
执行dmesg
命令,查看系统出错信息
主要原因就是因为内存不足引起的,根据前面的优化选项,要么增加logstash内存,要么减少批处理数据或工作线程数。