最近在网上看到的,就是项目很大的时候日志分散在十几台服务器上,查个报错像大海捞针。其实还是挺麻烦的,你想一下,如果万一哪里报错了让你查问题,我靠!那不得慢死呀!那么就"该上 ELK 了!" ELK(Elasticsearch、Logstash、Kibana)配合 Java 界的日志标准 SLF4J 和实力派 Logback,半小时就能打通任督二脉。
先搞清关系:
- SLF4J:日志门面(只定接口不干活)
- Logback:具体实现(真正写日志的伙计)
- Logstash:日志搬运工
- Elasticsearch:日志仓库
- Kibana:日志展示台
第一步:引入关键依赖(Maven示例)
xml
<!-- SLF4J 门面 + Logback 实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
<!-- Logback 直达 Logstash 的秘钥 -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
实测坑点:Spring Boot 自带 Logback,注意版本冲突,可以使用
mvn dependency:tree
揪出这个老六
第二步:配置 Logback.xml(核心戏法)
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 控制台输出(本地开发用) -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- ELK 专用输出管道 -->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- Logstash 服务器地址 -->
<destination>192.168.1.100:9250</destination>
<!-- 重要!JSON 编码器 -->
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<!-- 添加自定义字段 -->
<customFields>{"app": "order-service", "env": "prod"}</customFields>
<!-- 包含 MDC 数据(追踪ID必备) -->
<includeMdc>true</includeMdc>
</encoder>
<!-- 断线自动重连(生产环境保命符) -->
<reconnectionDelay>5000</reconnectionDelay>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="LOGSTASH" />
</root>
</configuration>
我踩过的坑:忘记配
reconnectionDelay
,网络波动导致日志静默丢失!
第三步:Logstash 配置(管道对接)
创建 logstash.conf
:
ruby
input {
tcp {
port => 9250
codec => json_lines # 关键解码器
}
}
filter {
# 添加服务器IP(动态字段)
mutate {
add_field => { "host_ip" => "%{host}" }
}
# 时间戳转换(解决时区问题)
date {
match => [ "timestamp", "ISO8601" ]
target => "@timestamp"
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "logs-%{app}-%{+YYYY.MM.dd}" # 按应用+日期分索引
}
}
启动命令:bin/logstash -f logstash.conf
第四步:Kibana 炫技时刻
- 访问
http://localhost:5601
- 进入 Stack Management > 索引模式 ,创建
logs-*
模式 - 在 Discover 选择索引,瞬间看到日志瀑布流!
惊喜功能:搜索
level:ERROR AND app:order-service
,3秒定位故障服务
高级技巧:分布式追踪
在代码中注入跟踪ID(Spring Boot示例):
java
@RestController
public class OrderController {
// 关键!注入跟踪ID
@GetMapping("/order")
public String createOrder(@RequestHeader String traceId) {
MDC.put("traceId", traceId); // 放入日志上下文
logger.info("创建订单开始...");
// 业务逻辑...
logger.info("订单创建成功");
MDC.remove("traceId"); // 请求结束清除
return "OK";
}
}
在 Kibana 中搜索 traceId:"123abc"
,整条请求链路一览无余!
性能优化实测数据
我在4核8G服务器压测对比:
方案 | 日志量/秒 | CPU占用 | 网络流量 |
---|---|---|---|
直接写文件 | 12,000 | 38% | 0 |
ELK原始TCP | 9,500 | 52% | 15MB/s |
异步队列优化 | 18,000 | 41% | 12MB/s |
异步配置加持(在Logback.xml追加):
xml
<appender name="ASYNC_LOGSTASH" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>1024</queueSize> <!-- 队列容量 -->
<discardingThreshold>0</discardingThreshold> <!-- 0表示队列满时阻塞 -->
<appender-ref ref="LOGSTASH" />
</appender>
黄金法则:生产环境必用异步!同步发送遇网络抖动直接拖垮应用
注意内容
-
日志洪灾 :Elasticsearch 默认堆内存1GB,生产至少4GB,修改
jvm.options
:diff-Xms4g -Xmx4g
-
字段爆炸:在ES设置中禁用动态映射:
jsonPUT /logs-*/_settings { "index.mapping.total_fields.limit": 1000 }
-
Logstash卡死:调整管道工作线程数(CPU核数+1):
rubyinput { tcp { threads => 5 # 按机器核数调整 } }