当前位置: 首页 > news >正文

使用logback异步打印日志

文章目录

  • 一、介绍
  • 二、运行环境
  • 三、演示项目
    • 1. 接口
    • 2. 日志配置文件
    • 3. 效果演示
    • 4. 异步输出验证
  • 四、异步输出原理
  • 五、其他参数配置
  • 六、源码分析
    • 1. 同步输出
    • 2. 异步输出
  • 七、总结

一、介绍

对于每一个开发人员来说,在业务代码中添加日志是至关重要的,尤其是后端开发,如果不打印日志,在接口出现bug的时候将无法定位bug;有了日志,即使接口出现bug,也可以通过查询日志很快的定位到bug的位置。

使用springboot开发的朋友使用最多的日志框架想必都是logback了吧,毕竟它是springboot官方推荐的日志框架,与springboot天然整合。再结合第三方工具lombok,当我们需要打印日志时只需要通过log.info("第一条日志");log.error("日志信息:{}", arg1);简单的代码即可完成打印。


如果接口中出现大量日志,且日志是直接输出到日志文件通过网络发送到其他服务器呢?这种场景下,将会出现较为耗时的磁盘IO网络IO,从而导致接口响应时间变长。

有没有办法通过异步的形式将日志打印出来呢?答案是肯定的,logback早就想到这一点了。请往下看。

二、运行环境

  • springboot:2.4.3
  • logback:1.2.3。logback是springboot自带的默认日志框架

该版本的springboot中自带该版本的logback,因此不必单独引入logback的依赖。

三、演示项目

本项目仅用于logback日志的异步打印,因此较为简单,仅包含一个接口和logback日志配置文件。

1. 接口

@Slf4j
@RestController
@RequestMapping("/student")
public class StudentController {@GetMapping("/insert")public String insert() {log.info("第一条日志");log.info("第二条日志");log.info("第三条日志");log.info("第四条日志");log.info("第五条日志");return "成功";}
}

2. 日志配置文件

logback提供了大量的Appender将日志输出到指定的位置。如ConsoleAppender用于同步地将日志输出到控制台FileAppender用于同步地将日志输出到指定日志文件SocketAppender用于同步地将日志通过套接字发送到指定服务器。他们都有一个共同点:同步

那么如何修改日志配置文件将日志输出改为异步呢?logback提供了一个Appender的异步实现类:AsyncAppender。使用方法也非常简单,同样也是通过在配置文件中添加<appender>标签声明AsyncAppender,然后通过引用属性引用一个同步Appender即可,如下所示

<?xml version="1.0" encoding="utf-8" ?>
<configuration><!-- 日志输出格式 --><property name="log.pattern"value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/><!-- 同步输出到控制台 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 异步输出 --><appender name="async-console" class="ch.qos.logback.classic.AsyncAppender"><!-- 引用同步,将其包装为异步 --><appender-ref ref="console" /></appender><!-- 采用异步输出 --><root level="INFO"><appender-ref ref="async-console" /></root></configuration>

3. 效果演示

我们使用postman调用接口,得到返回结果,如下图所示

在这里插入图片描述

查看控制台打印的日志,如下图所示

在这里插入图片描述

可这如何看出该日志打印和接口业务代码为异步的呢?

4. 异步输出验证

我们在AppenderAttachableImpl类的appendLoopOnAppenders()方法上添加断点,且要将该端点设置为多线程模式,如下图所示

在这里插入图片描述

此时再次调用接口,得到相同的结果,如下图所示

在这里插入图片描述

虽然接口已经正常响应了,但是我们发现代码却进入了断点,从该方法参数可以看出,在将要打印第一条日志时进入断点。如下图所示

在这里插入图片描述

且控制台上没有输出任何日志

在这里插入图片描述

当我们逐次放开断点使代码继续执行时,日志才逐行打印出来。因此我们可以断定接口业务代码与日志的打印为异步执行。

四、异步输出原理

为什么给同步Appender包装一层AsyncAppender就可以实现异步输出呢?

AsyncAppender内部维护了一个阻塞队列ArrayBlockingQueue,logback将我们打印日志的代码log.info("第一条日志")封装为一个事件Event,每当我们需要打印一行日志时,logback会将该事件放在阻塞队列中,然后再通过多线程的形式从该阻塞队列中获取一个事件执行。

阻塞队列可以保证日志的输出是有序的,多线程保证日志的输出是异步的。

五、其他参数配置

AsyncAppender能实现异步输出日志的关键因素是阻塞队列多线程,既然说到阻塞队列,那么必然少不了相关的参数。

参数类型说明
queueSizeint阻塞队列的最大容量,默认为256
discardingThresholdint默认地,当阻塞队列剩余容量达到20%时,logback将丢弃trace, debug和info三个级别的日志,而只输出warn和error级别的日志。如果需要全部输出,则将该值设置为0。
includeCallerDataboolean如果为true,logback对日志封装的事件中将包含更多调用者和父线程的信息,将降低性能。默认为false
maxFlushTimeint当服务停止时,logback将会等待一段时间,在这段时间内将正在输出的日志完成。
neverBlockboolean当阻塞队列已满时,如果为true,logback将丢失日志时间。默认为false

配置文件如下所示

<?xml version="1.0" encoding="utf-8" ?>
<configuration><!-- 日志输出格式 --><property name="log.pattern"value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/><!-- 同步输出到控制台 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 异步输出 --><appender name="async-console" class="ch.qos.logback.classic.AsyncAppender"><!-- 阻塞队列的参数配置 --><queueSize>256</queueSize><discardingThreshold>20</discardingThreshold><includeCallerData>false</includeCallerData><maxFlushTime>1000</maxFlushTime><neverBlock>false</neverBlock><!-- 引用同步,将其包装为异步 --><appender-ref ref="console" /></appender><!-- 采用异步输出 --><root level="INFO"><appender-ref ref="async-console" /></root></configuration>

六、源码分析

在logback中,任何日志的输出去都是通过start()方法完成的,接下来我们以ConsoleAppender同步输出 和 AsyncAppender异步输出为例,从源码层面分析。

1. 同步输出

进入ConsoleAppender源码,查看其start()方法。

在这里插入图片描述

可以看到其中第一行代码中通过target.getStream()获取输出目标的流,而target属性的声明如下所示,从该声明中我们看到通过target.getStream()获取输出目标的流就是System.out.print()了。这下我们就明白ConsoleAppender是如何将日志输出到控制台了。

在这里插入图片描述

再进入setOutputStream()方法查看其具体实现,从中可以看到是通过lock.lock()lock.unlock()来保证其同步执行的,其中lock所是一个非公平的可重入同步锁,这是多线程中同步锁AQS体系的概念,这里不详细展开,我们只需要知道通过该锁实现同步即可。

在这里插入图片描述

2. 异步输出

进入AsyncAppender源码,查看其start()方法,该方法定义在其父类AsyncAppenderBase中。

在这里插入图片描述

在该方法中我们看到第102行代码使用queueSize参数声明一个指定容量的阻塞队列,默认的discardingThreshold参数为阻塞队列容量的1/5,即20%,然后就是对worker属性进行设置,然后调用其start()方法。worker实际上是Thread类的子类Worker对象,调用其start()方法就是通过一个新线程调用该对象的run()方法。

在这里插入图片描述

从该方法中我们发现,无论是直接调用take()方法获取阻塞队列中的元素,还是通过遍历阻塞队列获取其中的元素,都会调用appendLoopOnAppenders()方法,而该方法就是logback真正输出日志的方法,也是我们在验证其异步输出是打断点的地方。

七、总结

  • logback通过AyncAppender实现日志的异步输出。
  • AyncAppender异步输出的原理是通过阻塞队列多线程实现的。


纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

相关文章:

使用logback异步打印日志

文章目录 一、介绍二、运行环境三、演示项目1. 接口2. 日志配置文件3. 效果演示4. 异步输出验证 四、异步输出原理五、其他参数配置六、源码分析1. 同步输出2. 异步输出 七、总结 一、介绍 对于每一个开发人员来说&#xff0c;在业务代码中添加日志是至关重要的&#xff0c;尤…...

ArcGIS Pro暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…...

Rabbitmq的消息确认

配置文件 spring:rabbitmq:publisher-confirm-type: correlated #开启确认回调publisher-returns: true #开启返回回调listener:simple:acknowledge-mode: manual #设置手动接受消息消息从生产者到交换机 无论消息是否到交换机ConfirmCallback都会触发。 Resourceprivate Rabb…...

在飞机设计中的仿真技术

仿真技术在飞机设计中发挥着越来越重要的作用&#xff0c;本文阐述了国内外在飞机设计中广泛使用的结构强度计算&#xff0c;多体动力学仿真、多学科多目标结构优化、内外流场分析、非线性有限元分析、疲劳强度分析、电磁仿真分析&#xff0c;机电液联合仿真分析等&#xff0c;…...

(2023Arxiv)Meta-Transformer: A Unified Framework for Multimodal Learning

论文链接&#xff1a;https://arxiv.org/abs/2307.10802 代码链接&#xff1a;https://github.com/invictus717/MetaTransformer 项目主页&#xff1a;https://kxgong.github.io/meta_transformer/ 【注】&#xff1a;根据实验结果来看&#xff0c;每次输入一种数据源进行处…...

解决Python读取图片路径存在转义字符

普遍解决路径中存在转义字符的问题的方法 普遍解决转义字符的问题&#xff0c;无非是以下这三种。 一、在路径前添加r 直接在路径前面加r&#xff0c;这种方法能够使字符保持原始的意思。 比如下面这种&#xff1a; pathr"D:\MindSpore\Dearui\source\ces\0AI.png&qu…...

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases&#xff0c;下载最新版安装文件&#xff0c;例如&#xff0c;3.1.6.1 版&#…...

混合云环境实现K8S可观测的6大策略

2023年&#xff0c;原生云应用及平台发展迅猛。大量企业都在努力发挥其应用程序的最大潜力&#xff0c;以确保极致的用户体验并推动业务增长。 混合云环境的兴起和容器化技术(如Kubernetes)的采用彻底改变了现代应用程序的开发、部署和扩展方式。 在这个数字舞台上&#xff0c;…...

音视频 FFmpeg命令行搭建

文章目录 一、配置二、测试 一、配置 以FFmpeg4.2.1 win32为例 解压ffmpeg-4.2.1-win32-shared.zip 拷⻉可执⾏⽂件到C:\Windows拷⻉动态链接库到C:\Windows\SysWOW64 注&#xff1a;WoW64 (Windows On Windows64)是⼀个Windows操作系统的⼦系统&#xff0c;被设计⽤来处理许…...

​ORACLE wallet实现无需输入用户名与密码登陆数据库 注意修改目录权限

wallet权限 linux 777 windows 需要修改.lck文件的owner 在ORACLE 10G前&#xff0c;我们在SHELL或JDBC中连接数据库时&#xff0c;都需要输入用户名与密码&#xff0c;并且都是明文。从1OGR2开始&#xff0c;ORACLE提供wallet这个工具&#xff0c;可以实现无需输入用户名与密…...

linux - 用户权限

认知root用户 无论是Windows、Macos、Linux均采用多用户的管理模式进行权限管理 在Linux系统中,拥有最大权限的账户名为: root(超级管理员) root用户拥有最大的系统操作权限&#xff0c;而普通用户在许多地方的权限是受限的。普通用户的权限&#xff0c;一般在其HOME目录内是不…...

计蒜客T1115——字符串判等

水题不解释&#xff0c;考研复习压力偶尔写一道换换心情还不错~ 这里有一个比较有趣的知识点&#xff0c;对于同时输入多个字符串时还要允许空格的输入&#xff0c;那么普通的cin函数就不能满足要求了&#xff0c;这里采用getline函数解决&#xff0c;如下&#xff1a; string …...

Android Framework工具——EA画图

EA 是一个著名的企业架构(Enterprise Architecture)工具,用于绘制和管理企业的架构图和过程模型。该工具提供了多种功能,包括建立业务流程图、数据流图、组织结构图、应用架构图等。EA工具可帮助企业进行战略规划、业务流程改进和系统开发等活动。 一、时序图 时序图(Seq…...

使用MyEclipse如何部署Descriptor (XML)编辑器?

Descriptor (XML) Editor编辑器包含了高级的XML编辑功能&#xff0c;在本文中您将了解到这些编辑功能、Web XML编辑等&#xff0c;此功能包含在MyEclipse中可用。 MyEclipse v2023.1.2离线版下载 1. Web XML 编辑器 MyEclipse Web XML编辑器包括高级XML编辑功能&#xff0c;…...

Codeforces Round 889 (Div. 2)C题题解

文章目录 [Dual (Hard Version)](https://codeforces.com/contest/1855/problem/C2)问题建模问题分析1.按元素值分类讨论&#xff0c;正负不同时存在时2.若正负同时存在时代码 Dual (Hard Version) 问题建模 给定n个数&#xff0c;n不超过20&#xff0c;且每个数ai&#xff0c…...

无涯教程-Perl - Subroutines(子例程)

定义子程序 Perl编程语言中 Subroutine子程序定义的一般形式如下: sub subroutine_name {body of the subroutine } 调用该Perl Subroutine的典型方式如下- subroutine_name( list of arguments ); 在Perl 5.0之前的版本中&#xff0c;调用 Subroutine的语法略有不同&…...

Rpc异步日志模块

Rpc异步日志模块作用 在一个大型分布式系统中&#xff0c;任何部署的分布式节点都可能发生崩溃&#xff0c;试想如果用普通的办法&#xff0c;即先排查哪个节点down掉了&#xff0c;找到down掉的节点后采取调试工具gdb调试该节点&#xff0c;进而排查宕机的原因。这中排查方法…...

python-pip

pip 路径 python 下载后自带pip ,在scripts 下&#xff0c;如 D:\install\python\Scripts numpy pip3 install numpy scipy matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simplepandas D:\install\python\Scripts>pip3 install pandas -i https://pypi.tuna.tsingh…...

无涯教程-Perl - getppid函数

描述 该函数返回父进程的进程ID。 语法 以下是此函数的简单语法- getppid返回值 该函数返回父进程的进程ID。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl$ppidgetppid();print "Parent Process ID $ppid\n";执行上述代码后,将产生以下输出- Paren…...

AUTOSAR规范与ECU软件开发(基础篇)1.2 汽车电子控制系统的基本构成

目录 前言 1、 传感器 2、 电子控制单元(ECU) 3、 执行器 前言 汽车电子控制系统主要由传感器(Sensor) 、 电子控制单元(Electronic Control Unit, ECU) 和执行器(Actuator) 组成(图1.1) ,对被控对象(Controlled Object)...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...