相关资料
- Logstash最佳实践,内容简练,如果解决不了问题,再移步官方文档
- 官方文档中有原理讲解,以及重要配置。最重要的三个章节为input、filter、output。很多时候都需要从这三个章节中学习。
使用步骤
- 目前每个logstash数据流都是一个单独的目录。意思是当有新的logstash作业时,重新解压出一份或者拷贝一份出来,再编写配置文件。
- 每个logstash作业核心内容是配置文件的编写。 这个配置文件我一般都直接放在logstash目录中。
- 启动参数:
bin/logstash -f first-pipeline.conf --config.test_and_exit能验证配置文件写的是否正确,但是也挺费时间的。因为logstash启动就是慢bin/logstash -f first-pipeline.conf --config.reload.automatic配置文件变化,能够感知并重新reload【和input的类型有关系,比如kafka就支持配置文件重载,读文件就不行】
配置相关logstash.yml
- logstash写入时,es接受请求的线程池触发拒绝策略,从es日志中可以观察到。这种情况不是去调线程池队列大小,而是去优化logstash写入策略!解决方案:调整其吞吐策略。配置如下:
# 吞吐量相关
pipeline.batch.size: 5000
pipeline.batch.delay: 500
- logstash官方文档对其能够配置的选项有详细的说明,建议仔细研读。
- 高版本logstash和es通信是
http,理论上升级es可以不升级logstash - logstash是用来解析处理消费的数据的,其中默认不支持转义,需要自行在配置中进行开启。深坑!配置如下:
# 支持转义
config.support_escapes: true
input
这里记录一下我用到过的input。
kafka
# 这就是最简单的一个例子
input{
kafka{
# 默认值就是latest
auto_offset_reset => "latest"
# 可以显示的指定消费者组的名字
group_id => "xxxx"
bootstrap_servers => "172.20.13.181:9092,172.20.13.182:9092,172.20.13.182:9092"
# 可以消费多个topic,
topics => ["test"]
}
}
熟悉kafka消费模式的话,是可以消费一个正则表达式的,例如topic-*,那么topic-1,topic-2...这些topic都会被消费。配置项为topics_pattern,如果配置了这个那么上面配置中的topics就失效。详细信息见官方文档。
还有一个场景,就是kafka消息的元数据我想拿出来怎么办,比如我想知道每条消息的offset、key这种东西。关于如何获取kafka消息的元数据。如果要拿到元数据有一个配置项decorate_events需要设置成true。下面的demo为获取元数据的配置:
input{
kafka{
bootstrap_servers => "172.20.13.181:9092,172.20.13.182:9092,172.20.13.182:9092"
topics => ["test"]
# 这个要配置成true
decorate_events => true
}
}
# 这些元数据需要在filter中我们通过mutute显示的加上
filter{
mutate{
# 这里我们的需求是拿到key
add_field => {'key' => '%{[@metadata][kafka][key]}'}
}
}
consumer_threads这个配置项设置消费的线程数,每个线程是一个消费者。一般消费者数量等于kafka-topic分区数。
jdbc
官方公众号,logstash同步db到es这个写的比较详细了。
根据我的经验,查询有两个场景,一个是每次都全量查询,这种查询没有状态可言,配置项比较少。
input {
jdbc {
jdbc_default_timezone =>"Asia/Shanghai"
jdbc_connection_string => "jdbc:oracle:thin:@//172.20.13.188:1521/xxxx"
jdbc_user => "xxxuser"
jdbc_password => "xxxpass"
# 得准备好对应的jar包。
jdbc_driver_library => "/god/data/elk/lib/ojdbc6-12.1.0.2.jar"
# jdbc对应厂商的驱动类
jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"
# cron表达式,每分钟执行一次查询
schedule => "* * * * *"
# 每次全量扫描表
statement => "select * from t_user where rownum < 5000"
}
}
另外一种是增量查询,这种时候就需要保存状态信息了。也就是上一次查询截止到哪里,这次得从上次结束的地方继续查。结合上面提到的官方公众号文章我列一下重要的配置项:
record_last_run => true是否记录上次执行的结果,这个默认是trueuse_column_valuetracking_columntracking_column_type这三个是要一起用的。例如我db表中有一个字段是snap_time,我需要以这个字段来增量同步,那么这三个字段一定要配置好。last_run_metadata_path => "mysql/last_id.txt"状态存在哪里
这个是官方的一个demo,追踪列是id。看他的statementsql语句中有一个:sql_last_value这实际上就是维护的那个状态值。
input {
jdbc {
statement => "SELECT id, mycolumn1, mycolumn2 FROM my_table WHERE id > :sql_last_value"
use_column_value => true
tracking_column => "id"
# ... other configuration bits
}
}
filter
dissect
将原始的消息按\t解析,并给每个字段起好了名字。
dissect {
mapping => {
"message" => "%{time}\t%{id}\t%{terminalNo}\t%{logId}\t%{IP}\t%{errCode}\t%{resp_time}\t%{attr}\t%{sequence}\t%{tid}\t%{checksum}\t%{version}"
}
}
ruby
ruby这块建议单独写成独立的脚本文件
ruby {
path => "./ruby-script/makeDate.rb"
}
grok
这个场景是从terminalNo中截取出前两个数字作为province
grok {
match => {
"terminalNo" => "(?<province>\d{2})"
}
}
translate
码值转换,场景为将省份编码翻译成中文
translate {
field => "province"
destination => "prov_zh"
dictionary => {
"11"=>"北京"
"12"=>"天津"
"13"=>"河北"
"14"=>"山西"
"15"=>"内蒙古"
"21"=>"辽宁"
"22"=>"吉林"
"23"=>"黑龙江"
"31"=>"上海"
"32"=>"江苏"
"33"=>"浙江"
"34"=>"安徽"
"35"=>"福建"
"36"=>"江西"
"37"=>"山东"
"41"=>"河南"
"42"=>"湖北"
"43"=>"湖南"
"44"=>"广东"
"45"=>"广西"
"46"=>"海南"
"51"=>"四川"
"52"=>"贵州"
"53"=>"云南"
"54"=>"西藏"
"50"=>"重庆"
"61"=>"陕西"
"62"=>"甘肃"
"63"=>"青海"
"64"=>"宁夏"
"65"=>"新疆"
}
fallback => "prov not match"
}
mutate
可以添加删除字段,例如:
mutate{
add_field => {'snap_time' => '%{index_date} %{time}+0800'}
add_field => {'key' => '%{[@metadata][kafka][key]}'}
remove_field => ['@timestamp','time','message']
}
output
通常output端就是ES。对于索引,有的数据流是每天产生一个新索引,有的则是每个月,有的则是每年。根据数据量来定。
output{
elasticsearch{
hosts => ["http://node1:9200"]
# 这里算是一个重点,%{index_date}这是filter中的字段,这里的场景是每天一个索引
index => "caslog-%{index_date}"
# 由于es配置了认证,所以需要相应权限的用户名和密码
user => "xxoo"
password => "123456"
}
}