前言:使用elk+kafka做日志归集,可以查看汇总日志,查看方便检索方便。避免了去一个个tomcat里面查看日志,而且要从头到尾去找自己所需要的信息。
Spring-boot项目将产生的日志生产到 Kafka,Logstash 消费 Kafka 中的消息,再推给 Elasticsearch,最终使用 Kibana 查看日志。
1.安装 ELK
- 在上篇博客有简单步骤讲解,简单安装 elk (Windows 环境)
2.安装zookeeper
因为 Kafka 依赖于 zookeeper,先安装 zookeeper。
- 下载zookeeper,http://mirror.bit.edu.cn/apache/zookeeper/,下载稳定版 ,例如: zookeeper-3.4.12
- 解压压缩包
- 打开zookeeper-3.4.12\conf,把zoo_sample.cfg重命名成zoo.cfg
- 修改配置文件内容,例:dataDir=E:/springcloud-log/zookeeper_data,端口号不变
- 运行zookeeper,打开 zookeeper-3.4.12\bin 目录 ,运行 zkServer.cmd
3.安装 Kafka
- 下载地址 http://kafka.apache.org/downloads.html 例:下载版本 kafka_2.12-2.0.0
- 打开 kafka_2.12-2.0.0\config ,配置 server.properties , 例:修改 log.dirs=E:/springcloud-log/kafka_log
- 启动 kafka 之前需启动 zookeeper 启动 kafka ,进入 kafka_2.12-2.0.0\bin\windows 目录 执行 kafka-server-start.bat ..\..\config\server.properties
- PS:启动报错示例:找不到或无法加载主类 ....
解决办法:
-
首先确保JAVA环境变量没有问题之后,修改 kafka-run-class.bat 中的179行给 %CLASSPATH% 加上双引号即可
set COMMAND=%JAVA% %KAFKA_HEAP_OPTS% %KAFKA_JVM_PERFORMANCE_OPTS% %KAFKA_JMX_OPTS%
%KAFKA_LOG4J_OPTS% -cp "%CLASSPATH%" %KAFKA_OPTS% %*
4.Spring-boot 项目改造
- 添加 pom 文件依赖
<!-- 日志同步至kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.2</version>
</dependency>
<dependency>
<groupId>com.github.danielwegener</groupId>
<artifactId>logback-kafka-appender</artifactId>
<version>0.1.0</version>
</dependency>
- 创建 logback-spring.xml 文件到 resources 目录下
xml内容:
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,
默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。 debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。
默认值为false。 -->
<!-- <configuration scan="false" scanPeriod="60 seconds" debug="false"> -->
<configuration>
<!--设置上下文名称,用于区分不同应用程序的记录。一旦设置不能修改, 可以通过%contextName来打印日志上下文名称 -->
<contextName>kafka-log-test</contextName>
<!-- 定义日志的根目录 -->
<property name="logDir" value="E:/springcloud-log/kafka-log" />
<!-- 定义日志文件名称 -->
<property name="logName" value="kafkaLog"></property>
<!-- ConsoleAppender 表示控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出格式: %d表示日期时间, %thread表示线程名, %-5level:级别从左显示5个字符宽度, %logger{50}
表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息, %n是换行符 -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 异常错误日志记录到文件 -->
<appender name="logfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- <Encoding>UTF-8</Encoding> -->
<File>${logDir}/${logName}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logDir}/history/${myspringboottest_log}.%d{yyyy-MM-dd}.rar</FileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="kafkaAppender" class="com.github.danielwegener.logback.kafka.KafkaAppender">
<encoder class="com.github.danielwegener.logback.kafka.encoding.LayoutKafkaMessageEncoder">
<layout class="net.logstash.logback.layout.LogstashLayout" >
<includeContext>false</includeContext>
<includeCallerData>true</includeCallerData>
<customFields>{"system":"kafka-log-test"}</customFields>
<fieldNames class="net.logstash.logback.fieldnames.ShortenedFieldNames"/>
</layout>
<charset>UTF-8</charset>
</encoder>
<!--kafka topic 需要与配置文件里面的topic一致 否则kafka会沉默并鄙视你-->
<topic>kafka-log</topic>
<keyingStrategy class="com.github.danielwegener.logback.kafka.keying.HostNameKeyingStrategy" />
<deliveryStrategy class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy" />
<producerConfig>bootstrap.servers=127.0.0.1:9092</producerConfig>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="logfile"/>
<appender-ref ref="kafkaAppender" />
</root>
</configuration>
- application.yml 文件添加配置
logging:
config: classpath:logback-spring.xml
5.调整 ELK 、Kafka 的配置文件
- 新建一个 Logstash 配置文件 logstash-spring-logback.conf
input {
kafka{
bootstrap_servers => ["127.0.0.1:9092"]
topics => ["kafka-log"] #数组类型,可配置多个topic
type => "kafka" #所有插件通用属性,尤其在input里面配置多个数据源时很有用
codec => "json"
}
}
output {
elasticsearch {
#ES地址
hosts => ["localhost:9200"]
#指定索引名字,不适用默认的,用来区分各个项目
index => "invo-log-%{+YYYY.MM.dd}"
}
stdout {}
}
PS:均使用默认端口号, topics 填写的内容和 logback-spring.xml 中的 <topic>kafka-log</topic> 一致。
- 修改 \kafka_2.12-2.0.0\config 下的 server.properties,添加配置
#启用删除策略
log.cleanup.policy=delete
#清理超过指定时间清理
log.retention.hours=24
- 其他组件按默认配置
6.启动测试
- 启动 zookeeper
- 启动 Kafka
- 启动 Elasticsearch
- 启动 Logstash,logstash -f ..\config\logstash-spring-logback.conf
- 启动 Kibana
- 启动两个 Spring-boot 服务端口号为 8080 和 8081,模拟集群效果,最后借助 zuul gateway 转发实现负载均衡效果,当执行一个业务时,第一段业务在 8080 服务上执行,第二段业务在 8081 服务上执行。登录 Kibana 查看日志。
两次请求负载均衡到 8080 和 8081 两台服务上,但是通过日志归集,我们可以顺序地查看到具体的日志了。而且 Kibana 可以根据日志级别检索日志,也可以通过关键字搜索相关日志,十分方便好用。