强哥之前有发过一篇文章:聊一聊项目中的日志配置,其中讲述了项目log4j日志配置文件中,通过修改一些参数实现日志分期保存以及保存文件个数限制相关问题以及相应的处理方式。当然如果日志量过大还是推荐项目中接入ELK将日志放入搜索引擎中进行后期的查询处理。
今天我们还是来讲讲日志,不过,不是关于日志的保存,而是关于在项目中遇到需要在程序中多处输出日志且每次的日志量都很大时,我们可以如何处理来提高程序的性能。
当程序逻辑复杂需要输出日志的点很多时(用于排查问题);当程序多个点需要输出日志,且每个点输出的日志内容较大时;当应用用户访问量大、并发高导致日志输出非常快时;当QA压测觉得你的程序性能较差时……
为了提升我们程序的性能,同时兼顾日志的输出而不至于对业务逻辑有较大的影响,无疑,我们要做的就是将日志的输出从业务逻辑的中剥离出来,更准确的将应该是通过异步的方式,使得日志输出对业务影响降到最小,同时不影响我们必要的日志的输出和保存。
异步日志输出:
接下来我们也就简单的讲解一下,在Springboot项目中(使用log4j2),如何配置上全局的异步日志以及如何验证程序确实开启了异步日志输出。
首先提一下为什么要使用log4j2吧,因为在log4j版本中,异步输出日志的功能问题还比较多,性能上也差了许多,今天发的另一篇会展示两者的差异。所以,在0202年当下,还是建议大家能够将log4j升级到log4j2。当然,如果你使用的是logback日志工具,它同样也带有开启异步日志输出的方式,大家感兴趣的可以自行百度。
其实Springboot配置log4j2异步输出日志方式比较简单,有混合模式和全模式,官方也比较推荐使用全异步模式,最大提升性能。所以强哥这里也就只提一下全异步模式的配置方式:
步骤一、添加依赖:
<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version></dependency>
步骤二、修改启动类或在项目启动时语句中加入属性参数:
修改启动类:
@SpringBootApplicationpublic class TestApplication {public static void main(String[] args) {//下面语句使得日志输出使用异步处理,减小输出日志对性能的影响 System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"); SpringApplication.run(TestApplication.class, args); }}
修改项目启动语句:
java -jar -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector xxx.jar
两种方式选择一种就行。按个人喜好处理。
没错,就上面简单的两步就能实现在项目启动后,异步日志的功能。当然,有的人可能还会问:配置是配置上了,可是到底是不是真的实现异步日志输出了呢?要怎么验证呢?
这里,我们可以通过查看项目启动后的线程名来检查是否真的配置成功了。下面是强哥在启动项目后,项目中的线程情况截图:
可以看到,有两个线程是关于Log4j2的,其中上面红框中的Log4j2-TF-AsyncLogger就是异步日志输出线程。看到它说明我们的配置是成功的。如果还是不确定,可以Debug模式运行项目,选择该线程,ide会进入到该线程查看程序到达该线程的一系列的操作,由此便可以知道成功配置了异步日志输出功能。
好了,上面便是Springboot实现log4j2异步输出日志的相关实现。其实内容相对简单,但是强哥更希望传递的是当大家遇到问题的时候,能够想到相应的解决方式,对于项目中与业务逻辑并非必要但是却影响性能的地方,完全可以通过异步或拆分的方式来保证性能。
这里没有讲解过多的原理,只是因为网上相应的原理说明确实太多,但是如何配置实现却都含糊不清,大家对原理等有兴趣也可以自己多去了解,这里只做抛砖引玉的作用啦,只希望大家遇到日志相关的瓶颈时,可以想到此解决方式。