java 多线程 异步日志_精彩技巧(1)-- 异步打印日志的一点事

本文探讨了在高并发、低延迟需求的系统中,同步日志打印存在的问题以及如何通过异步日志解决。详细介绍了同步日志模型和异步日志模型的工作原理,并讲解了如何配置logback实现异步日志,特别强调了队列大小、丢弃策略和neverBlock参数在避免线程阻塞中的关键作用。
摘要由CSDN通过智能技术生成

一、前言

最近刚刚结束转岗以来的第一次双11压测,收获颇多,难言言表, 本文就先谈谈异步日志吧,在高并发高流量响应延迟要求比较小的系统中同步打日志已经满足不了需求了,同步打日志会阻塞调用打日志的线程,而打日志本身是需要写磁盘的,所以会造成rt增加。异步日志就是为了解决这个问题。

二、日志打印模型

同步日志模型

b5199b0b0183a622c6c9c7197c63ac89.png

如上图,多个业务线程打印日志时候要等把内容写入磁盘后才会返回,所以打日志的rt就是写入磁盘的耗时。

异步日志模型

8cdb56730b7b8ac88c0f465dd7caa682.png

如上图多个业务线程打印日志时候是把打印任务放入内存队列后就直接返回了,而具体打印日志是有日志系统的一个日志线程去队列里面获取然后执行,可见这种打印rt就是写入内存队列的耗时。

三、关于异步日志的一些事

异步日志设置

f62b683d777c296ddda84480b54d5935.png

对于logback来说异步日志里面的队列是一个有界ArrayBlockingQueue,其中queueSize是队列大小,taskLogAppender是引用的普通同步日志

discardingThreshold是一个阈值,通过下面代码看他的作用:

032c2a45a6d964d098d479d14a6a354f.png

当队列的剩余容量小于这个阈值并且当前日志level TRACE, DEBUG or INFO ,则丢弃这些日志。

在压测时候代码配置如上,也就是配置了异步日志,但是还是出现了线程阻塞在打日志的地方了,经查看是阻塞到了日志队列ArrayBlockingQueue的put方法:

eaa10f9ca8a9d16b44fb843303232c06.png

可知put方法在队列满时候会挂起当前线程。那么如何解那?

上面介绍了discardingThreshold,可知本文设置为0说明永远不会丢弃日志level TRACE, DEBUG or INFO的日志,只要discardingThreshold>0则当队列快满时候level TRACE, DEBUG or INFO的日志就会丢弃掉,这个貌似可以解决问题。但是如果打印的是warn级别的日志那?还是会在put的时候阻塞。

通过看代码发现最终写日志时候有个判断:

3d30b2a17a97db1d30260ef45c5c294b.png

如果设置了neverBlock=true则写日志队列时候会调用ArrayBlockingQueue对的offer方法而不是put,而offer是非阻塞的:

ce1ae595c5f91ab2c9cebcd1977df49b.png

可知如果队列满则直接返回,而不是被挂起当前线程。 所以配置异步appender时候如下:

12478b88f8f0c69640db8487783eddc2.png

四 、总结

在高并发低延迟要求的系统里面不重要的日志可以设置为异步并且要注意设置队列满则丢弃策略,防止业务线程被挂起从而影响rt。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值