异步打印日志的一点事
2017-12-15 15:04
211 查看
异步打印日志的一点事
一、前言
最近刚刚结束转岗以来的第一次双11压测,收获颇多,难言言表, 本文就先谈谈异步日志吧,在高并发高流量响应延迟要求比较小的系统中同步打日志已经满足不了需求了,同步打日志会阻塞调用打日志的线程,而打日志本身是需要写磁盘的,所以会造成rt增加。异步日志就是为了解决这个问题。二、日志打印模型
同步日志模型![](http://upload-images.jianshu.io/upload_images/5879294-82349c0809788fb0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
如上图,多个业务线程打印日志时候要等把内容写入磁盘后才会返回,所以打日志的rt就是写入磁盘的耗时。
异步日志模型
![](http://upload-images.jianshu.io/upload_images/5879294-f2f99056e468cb53.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
如上图多个业务线程打印日志时候是把打印任务放入内存队列后就直接返回了,而具体打印日志是有日志系统的一个日志线程去队列里面获取然后执行,可见这种打印rt就是写入内存队列的耗时。
三、关于异步日志的一些事
异步日志设置![](http://upload-images.jianshu.io/upload_images/5879294-6b877e0a912de7f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
对于logback来说异步日志里面的队列是一个有界ArrayBlockingQueue,其中queueSize是队列大小,taskLogAppender是引用的普通同步日志
discardingThreshold是一个阈值,通过下面代码看他的作用:
![](http://upload-images.jianshu.io/upload_images/5879294-6280d0c066d24845.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
当队列的剩余容量小于这个阈值并且当前日志level TRACE, DEBUG or INFO ,则丢弃这些日志。
在压测时候代码配置如上,也就是配置了异步日志,但是还是出现了线程阻塞在打日志的地方了,经查看是阻塞到了日志队列ArrayBlockingQueue的put方法:
![](http://upload-images.jianshu.io/upload_images/5879294-1a171e57e39648a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可知put方法在队列满时候会挂起当前线程。那么如何解那?
上面介绍了discardingThreshold,可知本文设置为0说明永远不会丢弃日志level TRACE, DEBUG or INFO的日志,只要discardingThreshold>0则当队列快满时候level TRACE, DEBUG or INFO的日志就会丢弃掉,这个貌似可以解决问题。但是如果打印的是warn级别的日志那?还是会在put的时候阻塞。
通过看代码发现最终写日志时候有个判断:
![](http://upload-images.jianshu.io/upload_images/5879294-890333eae5bc19a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
如果设置了neverBlock=true则写日志队列时候会调用ArrayBlockingQueue对的offer方法而不是put,而offer是非阻塞的:
![](http://upload-images.jianshu.io/upload_images/5879294-5f9fe876cd962300.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
可知如果队列满则直接返回,而不是被挂起当前线程。
所以配置异步appender时候如下:
![](http://upload-images.jianshu.io/upload_images/5879294-a2446011fc7f1160.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image.png
四 、总结
在高并发低延迟要求的系统里面不重要的日志可以设置为异步并且要注意设置队列满则丢弃策略,防止业务线程被挂起从而影响rt相关文章推荐
- log4j2日志异步打印(实例讲解)
- 异步日志打印的一些事
- log4j2 异步多线程打印日志
- log4j2日志异步打印 (3)
- 异步打印日志的配置
- mybatis中的一点优化问题(数据库连接分开,别名,日志打印)
- 关于嵌入式系统日志打印的一点建议
- hive中打印日志的几种方式实现 推荐
- 记录华为、魅族手机无法打印 Log 日志的问题
- 经常使用Log日志打印输出
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- 黑马程序员-IOS学习笔记 c语言 DEBUG 日志打印
- 关于Log4Net日志记录组件的一点应用
- 在springboot日志打印的过程中,大量打印JndiPropertySource信息
- [置顶] Android开发之封装log打印日志的工具类,实用logutils详细代码
- 分享一个Android 分类打印,及日志记录工具
- 每天学习一点编程(9)(用程序打印符号来表示当前手机的电量。)
- 日志打印位置的选择
- #关于xcode 日志打印中文变成编码的解决代码
- springboot整合mybatis将sql打印到日志(转)