1 架构设计
ELK 技术栈架构设计图:
从左往右看,
Beats
:主要是使用Filebeat
,用于收集日志,将收集后的日志数据发送给 Kafka,充当 Kafka 的生产者Kafka
:高性能消息队列,主要起缓冲层的作用Logstash
:数据采集引擎,可以从数据库采集数据到 ES 中,起筛选、过滤日志数据作用ElasticSearch
和Kibana
:展示数据
下面是例子全量的示意图:
Log4j2
:使用Log4j2
的原因是其性能更好,底层使用无锁并行框架,缺点是服务器的性能需要高一些app.log
:存储全量日志error.log
:存储异常日志xpack-watch
:通过触发器做一个错误日志的上报和告警功能,同过对接 api,推送到对应的负责人微信之类
2 Log4j2
在之前的 《Java基础笔记(日志,反射)》 文章中就有对 Log4j2
进行学习,这里再做一些知识盲点的笔记
slf4j
与 Log4j2
的区别:
slf4j
:全称是simple log facade for java
,即它是日志库的一个统一规范接口,其下的实现有很多,如:Log4j
,Log4j2
,LogBack
Log4j2
:Log4j
全称是Log for java
,即是上面接口的一个实现,Log4j2
是Log4j
的升级版本,提高日志输出的吞吐量
2.2 配置文件
参考文章:《Log4j2同步日志,混合日志和异步日志配置详解》
Log4j2
中记录日志的方式有同步日志和异步日志两种方式,其中异步日志又可分为使用 AsyncAppender
和使用 AsyncLogger
两种方式。上面的参考文章写得很详细了,这里不再赘述。
如下是输出日志的格式:
[%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}] [%level{length=5}] [%thread-%tid] [%logger] [%X{hostName}] [%X{ip}] [%X{applicationName}] [%F,%L,%C,%M] [%m] ## '%ex'%n
其代表的各自意义是:
[%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}]
:时间,UTC美国的时间,因为后期elk也是使用这个时区[%level{length=5}]
:日志级别[%thread-%tid]
:线程id[%logger]
:创建对应 logger 实例传入的 class[%X{hostName}]
:自定义 MDC 的字段,当前应用主机名称[%X{ip}]
:自定义 MDC 的字段,当前应用的 IP[%X{applicationName}]
:自定义 MDC 的字段,当前应用的 applicationName[%F,%L,%C,%M]
:%F
表示当前输出日志的文件名、%L
表示是日志输出所在的行数、%C
表示当前输出日志的类名、%M
表示当前输出日志所在的方法名[%m]
:日志输出的自定义内容##
:自行编的特殊约定分隔符,将普通信息和错误堆栈分隔开'%ex'
:错误信息,其中单引号是特殊约定%n
换行符
2.3 MDC
MDC 线程变量,它的作用就是自定义变量,可以看做为一个 Map
对象,供日志输出时使用,如上自定义输出格式的 [%X{hostName}]
,其中 %X
表示的就是自定义变量,使用 MDC 很简单,只要在调用日志输出之前,调用 MDC 的 put
方法设置变量即可,如果没有调用 put
方法,则输出日志时,该变量为空。
MDC.put("hostName", NetUtil.getLocalHostName());
MDC.put("ip", NetUtil.getLocalIp());
MDC.put("applicationName", applicationName);
3 Lombok
在以往日志输出的时候,都需要在对应类下创建诸如:
final static Logger logger = LoggerFactory.getLogger(IndexController.class);
的 Logger
实例,然后调用该实例的方法进行相对应的日志输出,这里引用一个简化代码的工具 Lombok
。
Lombok
是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,即能够在源码中不需要写一些通用的方法,但是在编译生成的字节码文件中会帮我们生成这些方法。(即使 IDE 也有自带自动生成方法的功能,但使用 Lombok
会使代码看起来更加简洁)
3.1 Lombok 的使用
导入依赖:
<!-- lombok 工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
同时 idea 也需要安装对应的插件,但我在插件搜索窗口搜索不到对应的插件,只能在浏览器下载后在进行安装,参考一下这篇文章 《idea安装 Lombok 插件》,注意下载与 idea 对应的版本。
常用的 Lombok
注解:
@NonNull
:判断是否为空,如果为空,则抛出java.lang.NullPointerException
@Data
:注解在类上;提供类所有属性的getting
和setting
方法,此外还提供了equals
、canEqual
、hashCode
、toString
方法@Setter
:注解在属性上;为属性提供setting
方法@Getter
:注解在属性上;为属性提供getting
方法@SneakyThrows
:这个注解用在方法上,可以将方法中的代码用try-catch
语句包裹起来,捕获异常并在catch
中用Lombok.sneakyThrow(e)
把异常抛出,可以使用@SneakyThrows(Exception.class)
的形式指定抛出哪种异常@Slf4j
:注解在类上;为类提供一个 属性名为log
的日志对像@NoArgsConstructor
:注解在类上;为类提供一个无参的构造方法@AllArgsConstructor
:注解在类上;为类提供一个全参的构造方法@Builder
:提供了构造者的模式
参考文章:《Lombok工具 : 常用注解介绍 (全)》