ArrayBlockingQueue的使用

异步日志打印模型概述

在高并发、高流量并且响应时间要求比较小的系统中同步打印日志已经满足不了需求了,这是因为打印日志本身是需要写磁盘的,写磁盘的操作会暂时阻塞调用打印日志的业务线程,这会造成调用线程的rt增加。

如图所示为同步日志打印模型。

在这里插入图片描述
同步日志打印模型的缺点是将日志写入磁盘的操作是业务线程同步调用完成的,那么是否可以让业务线程把要打印的日志任务放入一个队列后直接返回,然后使用一个线程专门负责从队列中获取日志任务并将其写入磁盘呢?这样的话,业务线程打印日志的耗时就仅仅是把日志任务放入队列的耗时了,其实这就是logback提供的异步日志打印模型要做的事,具体如图所示。

在这里插入图片描述
其实logback的异步日志模型是一个多生产者-单消费者模型,其通过使用队列把同步日志打印转换为了异步,业务线程只需要通过调用异步appender把日志任务放入日志队列,而日志线程则负责使用同步的appender进行具体的日志打印。

日志打印线程只需要负责生产日志并将其放入队列,而不需要关心消费线程何时把日志具体写入磁盘。

异步日志与具体实现

异步日志

在这里插入图片描述
AsyncAppender 继承自 AsyncAppenderBase,其中后者具体实现了异步日志模型的主要功能,前者只是重写了其中的一些方法。

由该图可知,logback 中的异步日志队列是一个阻塞队列,其实就是有界阻塞队列ArrayBlockingQueue,其中 queueSize表示有界队列的元素个数,默认为256个。

worker是个线程,也就是异步日志打印模型中的单消费者线程。

aai 是一个 appender的装饰器,里面存放同步日志的appender,其中 appenderCount 记录 aai里面附加的同步 appender 的个数。

neverBlock用来指示当日志队列满时是否阻塞打印日志的线程。

discardingThreshold 是一个阈值,当日志队列里面的空闲元素个数小于该值时,新来的某些级别的日志会被直接丢弃,下面会具体讲。

首先我们来看何时创建日志队列,以及何时 启动消费线程,这需要看AsyncAppenderBase 的 start方法。该方法在解析完配置 AsyncAppenderBase 的 xml 的节点元素后被调用。

在这里插入图片描述
由以上代码可知,logback使用的是有界队列 ArrayBlockingQueue,之所以使用有界队列是考虑内存溢出问题。

在高并发下写日志的QPS会很高,如果设置为无界队列,队列本身会占用很大的内存,很可能会造成OOM。

这里消费日志队列的 worker线程被设置为守护线程,这意味着当主线程运行结束并且当前没有用户线程时,该worker线程会随着JVM的退出而终止,而不管日志队列里面是否还有日志任务未被处理。

另外,这里设置了线程的名称,这是个很好的习惯,因为在查找问题时会很有帮助,根据线程名字就可以定位线程。

既然是有界队列,那么肯定需要考虑队列满的问题,是丢弃老的日志任务,还是阻塞日志打印线程直到队列有空余元素呢?要回答这个问题,我们需要看看具体进行日志打印的AsyncAppenderBase的append方法。

在这里插入图片描述
其中代码(5)调用了AsyncAppender重写的isDiscardable方法,该方法的具体内容为
在这里插入图片描述
结合代码(5)和代码(7)可知,如果当前日志的级别小于等于INFO_INT并且当前队列的剩余容量小于discardingThreshold则会直接丢弃这些日志任务。

下面看具体代码(6)中的put方法。
在这里插入图片描述
如果neverBlock被设置为false(默认为false)则会调用阻塞队列的put方法,而put是阻塞的,也就是说如果当前队列满,则在调用put方法向队列放入一个元素时调用线程会被阻塞直到队列有空余空间。

这里可以看下put方法的实现。

在这里插入图片描述
这里有必要解释下代码(9),当日志队列满时put方法会调用await()方法阻塞当前线程,而如果其他线程中断了该线程,那么该线程会抛出InterruptedException异常,并且当前的日志任务就会被丢弃。

在logback-classic的1.2.3版本中,则添加了不对中断进行响应的方法。

在这里插入图片描述
如果当前日志打印线程在调用blockingQueue.put时被其他线程中断,则只是记录中断标志,然后继续循环调用blockingQueue.put,尝试把日志任务放入日志队列。

新版本的这个实现通过使用循环保证了即使当前线程被中断,日志任务最终也会被放入日志队列。

如果neverBlock被设置为true则会调用阻塞队列的offer方法,而该方法是非阻塞的,所以如果当前队列满,则会直接返回,也就是丢弃当前日志任务。这里回顾下offer方法的实现。

在这里插入图片描述
最后来看addAppender方法都做了什么。

在这里插入图片描述
由如上代码可知,一个异步appender只能绑定一个同步appender。这个appender会被放到AppenderAttachableImpl的appenderList列表里面。

到这里我们已经分析完了日志生产线程把日志任务放入日志队列的实现,下面一起来看消费线程是如何从队列里面消费日志任务并将其写入磁盘的。

由于消费线程是一个线程,所以就从worker的run方法开始。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/320938.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker部署ng实现反向代理

场景 按规定尽可能减少开放到外网的端口,所以需要将多个服务部署到一个ip一个端口上。 方案 使用ng实现请求转发。根据http请求中的host与ng配置文件中的server_name匹配,转发到对应的机器上。 在docker上部署三个容器,每个容器中启动一个…

JavaScript系列——Promise

文章目录 概要Promise三种状态状态改变Promise链式调用Promise处理并发promise.all()promise.allSettled()Promise.any()promise.race() 小结 概要 Promise中文翻译过来就是承诺、预示、有可能的意思。 在JavaScript里面,Promise 是一个对象…

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题(正式赛)

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 理论技能与职业素养(100分) 2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 【注意事项】 Geek极安云科专注技能竞赛技术提升,基于各大赛项提供全面的系统性…

【JAVA】哪些集合类是线程安全的

🍎个人博客:个人主页 🏆个人专栏:JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 Vector: HashTable: Collections.synchronizedList()、Collections.synchronizedSet()、Collections.syn…

网络地图服务(WMS)详解

文章目录 1.概述2.GetCapabilities3.GetMap4.GetFeatureInfo 阅读本文之前可参考前文:《地图服务器GeoServer的安装与配置》与《GeoServer发布地图服务(WMS、WFS)》。 1.概述 经过前文的介绍,相信我们对WMS/WFS服务已经有了一个非…

收银系统源码收银系统OEM定制开发(收银POS+线上商城+ERP+营销插件+聚合支付)

源码:零售行业线下线上一体化收银系统 1.开发语言 核心开发语言: php、HTML5、JavaPHP开发环境:php7.3安卓端收银、助手: 原生的JavaPC收银端: HTML5vuecssjsnwjs微信小程序助手: 原生小程序开发商城: uniapp后合管理网站: HTML5vueelement-uicssjs 2…

基于Java SSM框架实现在线作业管理系统项目【项目源码】计算机毕业设计

基于java的SSM框架实现在线作业管理系统演示 JSP技术 JSP技术本身是一种脚本语言,但它的功能是十分强大的,因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时,它可以使显示逻辑和内容分开,这就极大的方便了运动员的需求…

day01

文章目录 创建Vue实例插值表达式响应式数据常见标签v-htmlv-show v-ifv-if v-else-if v-elsev-onv-bindv-forv-model 综合案例 创建Vue实例 <!--创建Vue实例&#xff0c;初始化渲染1. 准备容器2. 引包&#xff08;官网&#xff09; — 开发版本/生产版本3. 创建Vue实例 ne…

配置DNS

vim /etc/named.conf vim /etc/named.rfc1912.zones cp named.localhost ./kgc.com.zone -p vim kgc.com.zone 设置备用dns服务器 修改主配置文件&#xff0c;并自动同步到从服务器

Zung氏焦虑症测试SAS

SAS被称为焦虑自评量表&#xff0c;是一种用来测量焦虑症状程度以及观察治疗过程中变化情况的心理量表。主要用于评估心理状态&#xff0c;辅助参考数据&#xff0c;也是焦虑评定的标准。焦虑自评量表系是由William W.K. Zung编制的&#xff0c;该量表已成为心理咨询师、心理医…

COBOL语言 :一种主要专注于解决业务问题的编程语言

译文&#xff1a; 什么是COBOL? COBOL是一种主要专注于解决业务问题的编程语言。COBOL的完整形式是面向业务的通用语言。它主要用于公司和政府的商业、金融和行政系统。这种语言也被用来解决许多数据处理问题。 它是由CODASYL(数据系统语言会议)开发的。它被用作大型机中的一…

解决报错:AttributeError: module ‘torch‘ has no attribute ‘_six‘

报错代码&#xff1a; if torch._six.PY3:import importlibimport importlib.utilimport sys这里的意思是判断你的python版本是否是python3&#xff0c;如果是PY37&#xff0c;就是判断你的python版本是不是python3.7&#xff0c;源码&#xff1a; PY37 sys.version_info[0]…

Keil5如何生成反汇编文件

Keil5如何生成反汇编文件 在Keil5界面下点击选项&#xff0c;选择“User”&#xff0c;勾选“After Build/Rebuild”中“RUN #1”&#xff0c;复制fromelf --text -a -c --outputxxx.dis xxx.axf 在Linker栏中找到“Linker Control string”里最后-o后的.axf文件&#xff0c;将…

街机模拟游戏逆向工程(HACKROM)教程:[1]数据的存储与读取

简介 在计算机中&#xff0c;数据存储的介质一直在变化&#xff0c;从最早的穿孔纸带&#xff0c;到现在的固态硬盘。但存储的原理是一直没有变化的&#xff0c;在计算机中&#xff0c;我们所存储的数据&#xff0c;一直都是以二进制的形式被存储存在不同的介质中。 计算机用…

Jenkins基础篇--凭据(Credential)管理

什么是凭据 Jenkins的Credentials直译为证书、文凭&#xff0c;我们可以理解为它是钥匙&#xff0c;用来做某些事情的认证。 如Jenkins 和 GitLab交互时&#xff0c;需要添加GitLab的API令牌和登录凭证。 如Jenkins 添加从节点时&#xff0c;需要添加从节点的登录凭证或者Je…

Linux的DHCP工作原理和dns服务器

目录 一、DHCP原理 1.DHCP的好处 2.DHCP的分配方式 3.实验 二、dns服务器 1.什么是dns 2.dns域名解析 3、在内网搭建dns 一、DHCP原理 DCHP工作原理使用C/S架构 &#xff08;1&#xff09;第一步&#xff0c;客户端广播发送一个discover报文寻找DHCP服务器。 &#…

网络爬虫丨基于requests+mysql爬取猫眼热门电影数据做可视化分析

文章目录 写在前面实验描述实验内容遇到问题 写在后面 写在前面 本期内容&#xff1a;基于requestsmysql爬取猫眼热门电影数据做可视化分析 实验需求 anaconda丨pycharmpython3.11.4requestsmysql 项目下载地址&#xff1a;https://download.csdn.net/download/m0_68111267…

OceanBase 4.2特性解读:Show Trace全链路跟踪,助力快速问题定位与精准诊断

在分布式数据库环境下&#xff0c;慢 SQL 诊断是运维人员面临的一大挑战。在无法及时发现问题根本原因的情况下&#xff0c;可能会严重影响用户体验&#xff0c;甚至会导致业务服务不可用。相对于单机数据库&#xff0c;分布式数据库系统涉及多个节点、多组件的协同工作&#x…

苍穹外卖学习----出错记录

1.微信开发者工具遇到的问题&#xff1a; 1.1appid消失报错&#xff1a; {errMsg: login:fail 系统错误,错误码:41002,appid missing [20240112 16:44:02][undefined]} 1.2解决方式&#xff1a; appid可在微信开发者官网 登录账号后在开发栏 找到 复制后按以下步骤粘贴即…

玩转 openEuler (一)-- 系统安装

简介 openEuler 是一款开源操作系统。当前 openEuler 内核源于Linux&#xff0c;支持鲲鹏及其它多种处理器&#xff0c;能够充分释放计算芯片的潜能&#xff0c;是由全球开源贡献者构建的高效、稳定、安全的开源操作系统&#xff0c;适用于数据库、大数据、云计算、人工智能等…