Contents
  1. 1. 干掉logstash
  2. 2. 直接用logback发送日志
  3. 3. filebeat接收udp数据
  4. 4. filebeat + socat(内容太老废弃)

干掉logstash

传统ELK模式在收集日志方面使用logstash,在应用端创建一个java进程读取应用日志传送出去。
这种方式其实是比较臃肿和消耗资源的,假设有50个服务器就最少需要50个logstash进程,如果每个服务器有多个需要收集的log文件(不同的java进程),也要考虑每个文件的日志格式,特别是前期没有考虑ELK的情况,可能需要做很多工作让这些文件格式一致,若不能达成一致则可能要多个logstash解析。
针对这种情况,我们最好能有一个解决方案,把logstash去除掉,无缝衔接应用,解决log格式差异,而且对业务本身透明。

直接用logback发送日志

要干掉logstash,必须改变日志收集方式,我们找到了开源项目logstash-logback-encoder。
logstash-logback-encoder是logback的扩展,它的主要工作是帮我们把日志格式化成ELK标准的json格式,并且通过它发送到ELK。
通过maven把它构建进你的项目,要注意logback版本需要1.2.0或以上。
然后在你的logback.xml配置加上如下appender:

1
2
3
4
5
6
7
8
9
10
11
12
13
<appender name="stash" class="net.logstash.logback.appender.LogstashSocketAppender">
<host>filebeat-server</host>
<port>5111</port>
<includeContext>false</includeContext>
<customFields>{"appname":"your app name","host":"${HOSTNAME}"}</customFields>
<suffix class="ch.qos.logback.classic.PatternLayout">
<pattern>%n</pattern>
</suffix>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="stash" />
</root>
  • customFields 自定义的字段,推荐加上HOSTNAME,便于在负载均衡的情况下分辨具体的服务器。
  • Prefix/Suffix 在行首/行末增加点东西,这里表示在行末增加换行符,否则所有json格式日志写在一行,filebeat不认。

上面的配置使用udp方式把日志发送到filebeat server,udp相对于tcp来说对程序和业务基本无影响,就算接收端不能访问也不会阻塞网络或者进程,在内网传输推荐使用udp。

filebeat接收udp数据

新版filebeat 7.6.0 可以接收udp数据包,直接创建配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
filebeat.inputs:
- type: udp
max_message_size: 20KiB
read_buffer: 50MiB
host: "0.0.0.0:5111"

processors:
- decode_json_fields:
fields: ["@timestamp", "message", "logger_name", "thread_name", "level", "level_value", "appname", "podname"]
process_array: false
max_depth: 1
target: ""
overwrite_keys: true
add_error_key: true

queue.mem:
events: 10240
flush.min_events: 512
flush.timeout: 5s

output.elasticsearch:
hosts: ["10.22.0.44:9200","10.22.0.18:9200"]
index: "filebeat-bxr-app-pro-%{+yyyy.MM.dd}"
worker: 2
compression_leveledit: 1

setup.template:
name: "filebeat-bxr-app-pro"
pattern: "filebeat-bxr-app-pro-*"
enabled: false

setup.ilm.enabled: false

filebeat + socat(内容太老废弃)

filebeat 我们之前在做nginx access log传输的时候使用过,对他的处理能力比较认可,最新5.2版和5.0版配置有点差别。
实现logback直接发送日志后,我们需要在远端搭建filebeat接收udp数据并且转发给Elasticsearch。
其实也可以使用logstash,但是logstash是java开发的,对比filebeat使用go开发,并发性能理论上差点,我们做多个服务器日志转发所以选择并发性和处理能力较好的。
filebeat本身不支持监听udp端口,我们需要一个辅助工具:socat
socat负责监听udp并把数据转到标准输出,filebeat使用stdin输入数据:

1
socat -u -lf/var/log/socat.log udp-listen:5111,fork - | filebeat.sh -c /etc/filebeat/filebeat-dev.yml
  • -u 表示单向传输数据,从udp 5111端口到标准输出,默认双向传输
  • -lf 可以把日志写到文件,方便保存排错
  • fork 创建子进程处理实际数据

ps:测试过nc,在接收长日志,比如带stack trace的java ERROR日志,会接收不完整。

ilebeat5.2配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
filebeat.prospectors:
- input_type: stdin
json.message_key:
json.keys_under_root: true
json.overwrite_keys: true
output.kafka:
enabled: true
hosts: ["your_kafka:9092"]
topic: your_topic_name
worker: 2
keep_alive: 20s
output.console:
enabled: false
  • json.message_key 接收json格式数据
  • json.keys_under_root 把接收到的json字段放在顶端
  • json.overwrite_keys 字段相同则覆盖
  • output.kafka 输出到kafka,还有其他选择,比如logstash,redis,Elasticsearch等,具体参考文档
  • ~~output.console 输出到console,调试用 ~~

ok,现在应该可以在kibana看到你传输的java日志了。

Contents
  1. 1. 干掉logstash
  2. 2. 直接用logback发送日志
  3. 3. filebeat接收udp数据
  4. 4. filebeat + socat(内容太老废弃)