logstash-client主机
注:各个服务logstash之间无通信,通过kafka的group_id一致实现消息只消费一次的功能的伪集群
logstash采集与清洗数据到elasticsearch https://www.cnblogs.com/dyh004/p/9641377.html
https://www.jianshu.com/p/443f1ea7b640
在server和client上都安装logstash
[root@client src]# tar xf logstash-7.12.0-linux-x86_64.tar.gz -C /usr/local/
[root@client src]# mv /usr/local/logstash-7.12.0/ /usr/local/logstash
测试logstash
//输入采用标准输入,输出采用标准输出
[root@client src]# cd /usr/local/logstash/bin/
[root@client bin]# ./logstash -e 'input{ stdin{} } output{ stdout{} }'
The stdin plugin is now waiting for input:
hello world ---手动输入hello world
{
"message" => "hello wohello world",
"@version" => "1",
"host" => "client",
"@timestamp" => 2021-08-03T03:45:28.335Z
}
//使用Rubydebug显示详细输出,codec为一种编译器
[root@client bin]# ./logstash -e 'input{ stdin{} } output{ stdout{ codec=>rubydebug } }'
{
"message" => "hello world",
"@version" => "1",
"host" => "client",
"@timestamp" => 2021-08-03T03:49:21.673Z
}
用logstash将信息写入elasticsearch中
[root@client bin]# ./logstash -e 'input{ stdin{} } output{ stdout{ hosts=>["192.168.100.99:9200"] } }'
![clipboard.png](https://img-blog.csdnimg.cn/img_convert/4b0e35e2c5e25636fb664b825fe4bf8e.png#clientId=u3d2d1cb7-5276-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=474&id=udeb6163a&margin=[object Object]&name=clipboard.png&originHeight=593&originWidth=937&originalType=binary&ratio=1&rotation=0&showTitle=false&size=173845&status=done&style=none&taskId=ua0431fbb-b642-43ea-b857-a0125a4685b&title=&width=749.6)
修改logstash配置文件,让其收集系统日志/var/log/messages,并将其输出到屏幕上。
条件判断(condition)
Logstash从1.3.0版本开始支持条件判断和表达式。
表达式支持下面这些操作符:
- ==,!=,<,>,<=,>=
- =(匹配正则),!(不匹配正则)
- in(包含),not in(不包含)
- and,or,nand(非与),xor(非或)
- ()(复合表达式),!()(对复合表达式取反)
[root@server bin]# vim logstash.conf
input {
file{
path => "/usr/local/nginx/logs/access.log" //可以定义多个日志类型或目录
type => "nginx_access" //自定义日志的类型
start_position => "beginning"
}
}
input {
kafka {
bootstrap_servers => "192.168.108.173:9093"
auto_offset_reset => "latest"
group_id => "intfitms-log"
topics => ["intf-logs"]
codec => multiline {
pattern => "^%{TIMESTAMP_ISO8601} "
negate => true
what => "previous"
}
}
}
filter {
grok {
match => {
"message"=> "%{TIMESTAMP_ISO8601:logtime} %{GREEDYDATA:appName} \[%{GREEDYDATA:thread}\] %{LOGLEVEL:loglevel} %{GREEDYDATA:class} - %{GREEDYDATA:loginfo}"
}
}
date {
match => ["logtime","yyyy-MM-dd HH:mm:ss.SSS"]
target => "@timestamp"
locale => "cn"
timezone => "+08:00"
remove_field => "logtime"
}
mutate{
remove_field => ["thread","thread.keyword"] //移除字段
}
}
output {
if "AdviceInfo" in [message] {
file {
path => "/data/intf-%{+yyyy.MM.dd}.log"
codec => line {
format => "%{message}"} //输出为本地文件,日志格式不变
}
}
else{
elasticsearch {
hosts => ["192.168.100.99:9200","192.168.100.100:9200","192.168.100.101:9200"]
index => "test-%{+YYYY.MM.dd}" --可以根据主机名、ip、应用名称等来命名
}
}
}
[root@server bin]# ./logstash -f logstash.conf --执行
[root@server bin]# nohup ./logstash -f logstash.conf & --后台运行
如果日志过多,可以将日志缓存到redis,redis再写入elasticsearch
![clipboard.png](https://img-blog.csdnimg.cn/img_convert/e941098e18611e668fc2d755b8149fcb.png#clientId=u3d2d1cb7-5276-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=490&id=u025f17f4&margin=[object Object]&name=clipboard.png&originHeight=612&originWidth=1098&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88861&status=done&style=none&taskId=ude3695c1-121e-43d5-822a-3d324028290&title=&width=878.4)
filebeat
[root@server src]# curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.5.0-x86_64.rpm
[root@server src]# rpm -vi filebeat-6.5.0-x86_64.rpm
[root@server src]# vim /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
encoding: GBK
paths:
- /data01/filebeat/test.out
include_lines: ["AdviceInfo"]
scan_frequency: 10s
fields_under_root: true
fields:
log_ip: 133.38.137.168
log_name: intf-app
output.redis:
hosts: ["192.168.108.173"]
password: "7o&Oghn2Ou36"
port: 8001
db: 0
key: "intf-app-list"
[root@server src]# filebeat modules enable elasticsearch
[root@server src]# filebeat setup
[root@server src]# service filebeat start
grok匹配
性能
前段时间分析日志,由于印象中logstash的性能有限,在github上找到一段go写的日志采集且能发送ES的程序,在日志分割部分,想利用grok的灵活,继续在github上查找go实现grok的代码,组合形成一个新的日志采集程序。简单测试,功能实现。
在部署生产环境,发现日志采集的速度为1000EPS,修改参数也很难提升,开始意味是Elasticsearch所限,搭建elasticsearch集群后,依旧受限。之后,放弃grok功能,发现直接转发并写入ES,可以轻松达到30K EPS,相差30倍的性能且无法满足基本性能需求,直接丢弃grok。
调试
在grok调试中,由于采用是整个字段匹配,如果一处无法匹配,就会导致整个匹配失败。编写grok语句蛮痛苦的,需要不断尝试,更有可能是同样的字段,出现调试器异常有时匹配不成功的现象(包括kibana 6.3自带的)。
测试中遇到的坑如下:
- 涉及正则语法的字符需要使用转义,如’('、 ‘)’、 ‘[’、 ‘]’…
- 其他实现的grok语法,需要对‘\’再次转义,相当于“\”转义
- 如果DATA无法匹配,可以使用GREEDYDATA,或许有惊喜
- 记不清字符‘|’是否有转义,可以尝试下
经历几次艰苦的调试,已经对grok好感大幅降低,grok依附与logstash等,对于数据采集分割性能堪忧,基于性能,考虑放弃logstash,自然放弃这种模式。
此外,发现针对字段处理,可能使用mapping是更好的模式,将尝试使用新的方式。
grok预定字段
USERNAME [a-zA-Z0-9._-]+
USER %{
USERNAME}
INT (?:[+-]?(?:[0-9]+))
BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER (?:%{
BASE10NUM})
BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa