Plumelog与ELK集成Springboot
背景
在互联网应用中,日志作为一种特殊的数据,其作用和意义都非常重要。通过日志可以分析用户行为和习惯,监控系统中各服务的健康状况,功能使用频度,以及定位和分析系统中的Bug等。在时下流行的分布式、高负载的微服务架构中,查看和管理日志变得比较麻烦。 因为同一个服务会部署多套,很难确定用户的请求是由哪个服务响应,过程日志在哪台服务器上。因此,分布式日志管理组件也应运而生,常用的就有ELK,Plumelog等。
前段时间在对公司产品线的基础框架做重构时,有同事向我建议使用Plumelog来进行分布式服务的日志收集和管理。在升级之前,公司使用的是ELK,且已经积累了较多的使用经验,贸然去换多少有些武断,我决定对两者先做一些学习和实践,在充分了解它们的基础上,再去决定是否更换技术栈。本篇博客就是对这两项技术的实践的成果记录。
SpringBoot整合PlumeLog
一、Plumelog介绍
Plumelog是一种无代码入侵的分布式日志系统,它基于log4j、log4j2、logback搜集日志,拥有redis、kafka、lite、嵌入式版本plumelog-lite等多种启动模式,可以和Redis,Kafka等中间件搭配使用来高效的收集日志信息。全程不占应用程序本地磁盘空间,无需维护。它对于项目透明,不影响项目本身运行,基于elasticsearch作为查询引擎,高吞吐,查询效率高。
其系统架构如下:
二、SpringBoot集成Plumelog
1、下载安装ElasticSearch(ES),Redis, plume-log-server,可以点击名字链接到下载地址。(本次的实践环境为Windows环境,ES版本为8.16.1,plumelog版本为3.5)
2、修改ES中的elasticseash.yml配置,启动ES,Redis,修改plume-log-server中的配置并启动。
elasticseash中的配置文件位于\elasticsearch-8.16.1\config\elasticsearch.yml,修改如下:
# 集群名称
cluster.name: leixi-es
#节点名称
node.name: leixi-1
#数据存储位置
path.data: D:/software/elasticsearch-8.16.1/data/leixi
#日志存储位置
path.logs: D:/software/elasticsearch-8.16.1/logs/leixi
#默认端口
http.port: 9200
#集群中拥有的节点
cluster.initial_master_nodes: ["leixi-1"]
# X-Pack 安全功能是否启用
xpack.security.enabled: false
#用于控制 Elasticsearch 的 X-Pack 安全功能中的自动注册(enrollment)功能
xpack.security.enrollment.enabled: false
# 用于控制 Elasticsearch 的 X-Pack 安全功能中的 HTTP SSL/TLS 加密
xpack.security.http.ssl:
enabled: false
keystore.path: certs/http.p12
# 用于控制 Elasticsearch 的 X-Pack 安全功能中的传输层 SSL/TLS 加密
xpack.security.transport.ssl:
enabled: false
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
#IP地址
http.host: 0.0.0.0
可通过http://127.0.0.1:9200/来检查ES启动是否成功:
redis的windows启动如下:(redis-server.exe redis.conf, 其中redis.conf是同级目录下的redis配置文件。)
plume-log-server\application.properties里配置好ES和Redis的相关地址,如下:
spring.application.name=plumelog_server
spring.profiles.active=test-confidential
server.port=8891
spring.thymeleaf.mode=LEGACYHTML5
spring.mvc.view.prefix=classpath:/templates/
spring.mvc.view.suffix=.html
spring.mvc.static-path-pattern=/plumelog/**
spring.boot.admin.context-path=admin
#值为4种 redis,kafka,rest,restServer
plumelog.model=redis
#队列redis地址,model配置redis集群模式,哨兵模式用逗号隔开,队列redis不支持集群模式
plumelog.queue.redis.redisHost=127.0.0.1:6379
#如果使用redis有密码,启用下面配置
#plumelog.queue.redis.redisPassWord=
plumelog.queue.redis.redisDb=0
#哨兵模式需要配置的
#plumelog.queue.redis.sentinel.masterName=myMaster
#elasticsearch相关配置,Hosts支持携带协议,如:http、https
plumelog.es.esHosts=127.0.0.1:9200
plumelog.es.shards=5
plumelog.es.replicas=1
plumelog.es.refresh.interval=30s
#日志索引建立方式day表示按天、hour表示按照小时
plumelog.es.indexType.model=day
plumelog.es.maxShards=100000
#ES设置密码,启用下面配置
#plumelog.es.userName=elastic
#plumelog.es.passWord=elastic
#是否信任自签证书
#plumelog.es.trustSelfSigned=true
#是否hostname验证
#plumelog.es.hostnameVerification=false
#单次拉取日志条数
plumelog.maxSendSize=100
#拉取时间间隔,kafka不生效
plumelog.interval=100
#plumelog-ui的地址 如果不配置,报警信息里不可以点连接
plumelog.ui.url=http://demo.plumelog.com
#管理密码,手动删除日志的时候需要输入的密码
admin.password=123456
#日志保留天数,配置0或者不配置默认永久保留
admin.log.keepDays=30
#链路保留天数,配置0或者不配置默认永久保留
admin.log.trace.keepDays=30
#登录配置,配置后会有登录界面
#login.username=admin
#login.password=admin
启动plume-log-server后,可以通过http://127.0.0.1:8891/来访问plumelog控制台
3、创建Springboot应用,引入依赖包,添加测试方法。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.leixi.hub</groupId>
<artifactId>leixi-plumelog-client</artifactId>
<version>1.0</version>
<name>leixi-plumelog-client</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.plumelog</groupId>
<artifactId>plumelog-logback</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 19200
servlet:
context-path: /leixi
max-http-header-size: 102400
plumelog:
appName: leixiTest
redisHost: 127.0.0.1:6379
resources\logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--过滤trace日志到控制台-->
<filter class="com.plumelog.logback.util.FilterSyncLogger">
<level></level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 输出到文件 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>logs/plumelog-demo.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>3</MaxHistory>
</rollingPolicy>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 环境配置 -->
<springProperty scope="context" name="plumelog.appName" source="plumelog.appName"/>
<springProperty scope="context" name="plumelog.redisHost" source="plumelog.redisHost"/>
<springProperty scope="context" name="plumelog.redisPort" source="plumelog.redisPort"/>
<springProperty scope="context" name="plumelog.redisAuth" source="plumelog.redisAuth"/>
<springProperty scope="context" name="plumelog.redisDb" source="plumelog.redisDb"/>
<springProperty scope="context" name="plumelog.env" source="spring.profiles.active"/>
<!-- 输出plumelog -->
<appender name="plumelog" class="com.plumelog.logback.appender.RedisAppender">
<appName>${plumelog.appName}</appName>
<redisHost>${plumelog.redisHost}</redisHost>
<redisDb>${plumelog.redisDb}</redisDb>
<env>${plumelog.env}</env>
</appender>
<!-- 配置日志输出,只输出info,只保留控制台和plumelog输出-->
<!-- 正常开发环境本地,只输出到控制台,测试环境只输出到plumelog,生产环境输出到本地文件plumelog,因为有plumelog加持本地文件就保留3天即可-->
<!-- 这些都可以根据环境配置不同加载不同的ref-->
<root level="info">
<!--输出到控制台-->
<appender-ref ref="CONSOLE"/>
<!-- 输出到文件 -->
<appender-ref ref="file"/>
<!-- 输出plumelog -->
<appender-ref ref="plumelog"/>
</root>
</configuration>
添加一个用于测试的Controller方法:
package com.leixi.basic.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author 雷袭月启
* @since 2024/12/5 19:39
*/
@RestController
public class DemoController {
private final static Logger logger = LoggerFactory.getLogger(DemoController.class);
@GetMapping("/demo")
public Object demo(String str) {
logger.info("Get in demo, the str is:{} ", str);
return "Hello World";
}
@GetMapping("/inputNumber")
public Object inputNumber(String number) {
logger.info("Get in inputNumber, the str is:{} ", number);
int x = Integer.parseInt(number);
return " The Input Number is " + x;
}
}
完成以上配置,就可以启动项目,开始测试了。
4、测试。通过以下链接进行测试:
http://127.0.0.1:19200/leixi/demo?str=test
http://127.0.0.1:19200/leixi/inputNumber?number=1
http://127.0.0.1:19200/leixi/inputNumber?number=a
可以看到Springboot后端和plumelog控制台显示如下信息,说明plumelog确实收集到了Springboot应用中的日志信息,本次的实践是成功的:
Springboot整合ELK
一、ELK介绍
ELK是ElasticSearch、Logstash、Kibana三个应用的缩写。 三者说明如下:
Elasticsearch:是一个分布式的搜索和分析引擎,可以用于全文检索、结构化检索和分析,并能将这三者结合起来。Elasticsearch 基于 Lucene 开发,现在是使用最广的开源搜索引擎之一。
Logstash: 简单来说就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端,与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供了很多功能强大的滤网以满足你的各种应用场景。
Kibana: 是一个开源的分析与可视化平台,可用kibana搜索、查看存放在Elasticsearch索引里的数据,使用各种不同的图标、表格、地图等,kibana能够很轻易的展示高级数据分析与可视化。
ELK实现的日志采集的核心是,通过 logstash 将应用系统的日志通过 input 收集,进行内部整理,通过 output 输出到 Elasticsearch 中。 kibana作为可视化平台,将 ES 的数据输出到平台,通过图表的方式进行展示。
二、Springboot集成ELK
1、下载kibana, logstash,点击名称可以链接到下载地址,雷袭下载的是最新版8.16.1,与Elasticsearch的版本一致。因在上文中已经下载并启动了ES,所以这里不再赘述。(为方便测试,这里的ELK全部使用的是Winodws环境进行部署。大家参照博文实践时,请下载Windows版的安装包。)
2、配置kibana,logstash,简单来说,就是让它们和ES关联起来。
修改:\kibana-8.16.1\config\kibana.yml,添加或修改以下几行:
server.port: 5601 #端口号
server.host: "127.0.0.1" #IP地址
elasticsearch.hosts: ["http://127.0.0.1:9200"] #es的地址
i18n.locale: "zh-CN" #默认语言
#以下三个如果不配,会导致kibana查询日志信息时报错。
# 用于加密保存的对象(如仪表板、可视化等)的密钥。确保这些对象在存储时是加密的,增加安全性,可以随机生成一个
xpack.encryptedSavedObjects.encryptionKey: dcbf819d8874e8242eaf107d538fe874
#用于加密报表功能中的敏感数据的密钥。确保生成的报表中的敏感信息不会被未授权访问。可以随机生成一个
xpack.reporting.encryptionKey: ba2d98e6dad4fa73d77f5f34a568cfdd
#用于加密安全相关的数据(如会话、密码等)的密钥。确保 Kibana 中的安全功能能够安全地存储和传输敏感信息,可以随机生成一个
xpack.security.encryptionKey: 3871dfc1bd945e1141364e4244800b39
在logstash-8.16.1文件夹下创建一个insertlog.conf,内容如下:
input{
tcp {
mode => "server"
host => "127.0.0.1" #我这里是本地
port => 5044 #开放这个端口进行采集
codec => json_lines # 编解码器 有的版本需要独立安装
}
}
output{
elasticsearch{ #es地址
hosts=>["127.0.0.1:9200"]
# 在es里产生的index的名称
index => "leixi-logstash"
}
stdout{codec => rubydebug}
}
3、Windows启动kibana和logstash, kibana的启动较简单,直接点击kibana-8.16.1\bin\kibana.bat即可。logstash的启动需要关联刚才创建的文件,先在\logstash-8.16.1\bin打开cmd黑窗口,再执行logstash.bat -f insertlog.conf。(注意:logstash执行这行命令时会在logstash-8.16.1文件夹里去找insertlog.conf,我开始把insertlog.conf放在bin文件夹下,结果一直启动不成功。)
启动成功后,可以访问http://127.0.0.1:5601/ 来验证kibana的启动状况,访问http://127.0.0.1:9200/来验证logstash的启动情况,如下:
4、改造SpringBoot项目,改动内容如下:
pom.xml
<!--去掉该依赖-->
<!-- <dependency>-->
<!-- <groupId>com.plumelog</groupId>-->
<!-- <artifactId>plumelog-logback</artifactId>-->
<!-- <version>3.5.2</version>-->
<!-- </dependency>-->
<!--添加以下两个依赖-->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
logback-spring.xml改成如下样式:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:5044</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<root level="INFO">
<appender-ref ref="LOGSTASH" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
5、启动SpringBoot项目,仍然执行上述的测试用例,可以通过Kibana查询到应用的相关日志:
对比总结
综合上述的实践经历来看,Plumelog和ELK都能实现无侵入性的日志收集,日志展示,都需要Elasticseash。除此之外,PlumeLog在对环境搭建,参数配置方面,都比ELK要简单,占用的系统资源,所需的维护成本也相对更低,因此Plumelog显然比ELK更有性价比。
踩坑记录
在本地搭建Plumelog和ELK时, 雷袭也遇到了几块拦路石,可能和本地启动、ELK版本等有一定的关系,这里都记录下来,避免有人踩坑。
1、启动Redis时,使用的命令是redis-server.exe redis.windows.conf,但是这个redis.windiws.conf中的这一行没去掉#号,导致redis启动不成功,报错:
Creating Server TCP listening socket *:6379: listen: Unknown error
2、最新版的Elasticsearch8.16.1的配置文件elasticsearch.yml中添加了ssl认证的配置,且默认为true,如果不改为false,本地测试时会无法访问http://127.0.0.1:9200。
3、windows环境下,logstash执行启动命令logstash -f insertlog.conf 时,需要在\logstash-8.16.1\bin下执行,但是会在\logstash-8.16.1文件夹下找insertlog.conf文件,如果文件放错了位置,会启动不成功,且报错:
[logstash.config.sourceloader] No configuration found in the configured sources.
Logstash stopped processing because of an error: (SystemExit) exit
4、 kibana的日志查询是在Stack Management中根据索引来查询日志的,这个索引就是logstash配置文件中的index,如果kinaba的配置文件中没有以下几行,则查询日志时可能会查不出数据来。
xpack.encryptedSavedObjects.encryptionKey: ****
xpack.reporting.encryptionKey: ****
xpack.security.encryptionKey: ***
后记与致谢
本文只是一次很简单的Plumelog和ELK结合Springboot的搭建实践,实际上,这两款工具的功能都非常强大,像按照一定的格式设置日志字段,图表方式展示和汇总日志,通过各种中间件来收集日志,分布式日志的汇总和检索等,这些都是雷袭比较推崇但没有尝试的,大家可以自行实践。文末依然附上本次实践过程中参考的一些优秀博文,感谢大佬指路!
SpringBoot集成ELK详细教程
Windows版ELK日志分析系统搭建过程
Springboot 之 使用Plumelog分布式日志组件
分布式日志系统:Plumelog部署及系统接入