Logback 日志打印导致程序崩溃的实战分析
在软件开发和运维中,日志记录是必不可少的一环,帮我们追踪程序的行为,定位问题所在。然而,有时日志本身却可能成为问题的根源。本文将通过一个真实的案例来探讨 Logback 日志系统中的一个常见问题,当并发量大,日志打印突增时,导致程序崩溃。
一、Logback集成
下面来看下在 SpringBoot 中是如何集成 Logback 的,这虽然是个 demo,但在真实使用中也是这样的,无非是扩展一些功能而已,后面讲到 Logback 是程序崩溃也是基于这样的实现。
首先是添加依赖,关于 SpringBoot 相关的依赖就省略了,这里重点关注 Logback 的依赖,注意使用的版本,不同的版本有不同的表现。
<dependency><groupId>net.logstash.logback</groupId><artifactId>logstash-logback-encoder</artifactId><version>6.3</version>
</dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.1.8</version>
</dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.1.8</version>
</dependency>
Logback 配置文件添加,添加 logback-spring.xml 文件。
<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="true"><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><!-- 日志输出内容,根据实际情况进行调整 --><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 日志文件名及路径,根据实际情况修改 --><file>./logs/app.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/app.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern></encoder></appender><root level="info"><appender-ref ref="STDOUT" /><appender-ref ref="FILE" /></root>
</configuration>
然后项目中在需要打印日志的地方,直接使用 log.info 或 log.error 等方式打印日志就好了,是不是很简单。
二、程序崩溃案例
程序在运行过程中,会收到很多服务请求超时的预警,然后过一会就会收到服务重启的预警。而且服务重启是无规律可循的,不是固定在某一个服务的某些 pod 上,而是所有的服务都有重启的现象,然后马上查看了相关监控,发现了一下问题,以下是相关监控内容

open files数量突增

直接内存的使用会突增

CPU 使用率突增

线程数量也会突增
三、原因分析
通过监控发现,在程序重启过程中,CPU、HTTP线程、直接内存使用、Open Files 这些指标都会突增。
首先看 HTTP 线程突增,感觉像是程序哪里阻塞住了,然后导致 HTTP 的堆积,最终导致健康检查的请求进不来,最终导致了服务的重启,而服务重启后一切又都回归了正常,下次在出现这种情况,可能又出现在了别的 Pod 上。到底是哪里出了问题呢?
因为是 HTTP 线程突增,所以第一想到的是程序内部有阻塞点,然后再请求三方接口、数据库查询等依赖的地方都加上了耗时统计,然后再出现重启时在看一下到底是哪里阻塞住了,奇怪的是这些地方都很正常,响应时间也没什么变化。
没有办法只能生成重启时的线程堆栈情况了,联系运维,编写了相应的脚本,当服务发生重启时生成相应的线程堆栈,具体是使用 jstack 命令。通过线程堆栈信息最终才发现了问题所在。以下是详细的线程堆栈分析。
阻塞的线程统计情况如下:

尽然有857个 HTTP 线程被阻塞住了,具体在看下阻塞在哪里了呢。

通过线程堆栈信息可以清楚的看到,是在打印日志时发生了阻塞,大量的 HTTP 线程被阻塞住,无法接受新的请求,最终导致健康检查失败而发生了重启,重启后这些又回归了正常。
为什么会发生阻塞呢?
我们使用的 Logback 版本是1.1.8,根据堆栈信息定位到具体的阻塞点,源码如下:

写日志时采用的是同步写,同步写这里是有加锁操作的,目的是为了防止一个线程将写日志的流关闭导致其他线程无法写入日志,而且采用得还是公平锁。这就是问题的根源所在,在高并发场景下,大量的日志写入都要到这里获取锁才能进行日志写入,这就造成了阻塞,将 HTTP 线程耗尽。
公平锁就是多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能获取到锁。这样虽然可以方式线程饥饿,但是吞吐量会下降很多,队列里除了第一个线程,其他的线程都会被阻塞。
四、解决方案
为了解决上述问题,可以采用如下策略进行修改。
首先,优化日志输出策略,平时在我们的系统重只输出必要的 info 日志和 error 日志,其他的 debug 级别日志和 warn 级别的日志就不用输出了。接口只打印入参,不要打印出参,一般情况下出参都会比较大,还有一些 SQL 语句的日志,这些都会加大日志的输出量。要想解决上述问题,第一条就是减少日志的输出,这也是这次问题解决的第一条方案:对项目中的日志进行梳理并且规范化,debug 级别和 warn 级别的日志统统下掉,简化系统日志输出量,将接口返回值和 SQL 语句的日志省略掉。当然了如果生产环境为了排查问题方便,可以开发一个开关功能,可以在排查问题时打印相应的日志。
其次,升级 Logback 日志版本,目前使用的版本是 1.1.8,将版本升级为 1.2.3,升级以后将公平锁修改为了非公平锁。
使用非公平锁后,在并发场景下可以减少线程切换次数,从而提高整体性能。同时也能减少线程的等待时间。
然后,可以将日志输出由同步改为异步输出,在同步输出模式下,日志记录操作会阻塞调用线程,这意味着每当调用logger.info()等方法时,应用程序必须等待日志消息被写入磁盘或其它目的地后才能继续执行。
同步模式下日志记录逻辑简单,易于理解和调试,日志输出的顺序与记录顺序一致,这对于日志分析非常有利。但是容易出现性能瓶颈,上述的案例就是同步模式造成的。
在异步输出模式下,日志记录操作不会阻塞调用线程,而是将日志消息放入一个队列中,由一个或多个后台线程负责从队列中取出消息并写入目的地。
异步模式可以显著提高性能,减少对主线程的影响。由于消息可能被不同的时间被处理,所以输出的日志顺序可能与记录顺序不一致,如果队列满了,还可能造成日志消息的丢失。
在Logback中,可以使用ch.qos.logback.classic.AsyncAppender来实现异步日志输出。
五、总结
日志记录是必不可少的一环,帮我们追踪程序的行为,定位问题所在。然而,有时日志本身却可能成为问题的根源。所以要根据实际情况选择合适的日志输出方式,避免造成程序阻塞而导致业务收到影响。
往期经典推荐:
从理论到实践:零拷贝技术的全面解读_零拷贝详解-CSDN博客
Sentinel与Nacos强强联合,构建微服务稳定性基石的重要实践_nacos sentinel-CSDN博客
从0开始理解云原生架构-CSDN博客
TiDB高手进阶:揭秘自增ID热点现象与高级调优技巧_tidb 分布式自增id-CSDN博客
深入浅出 Drools 规则引擎-CSDN博客
相关文章:
Logback 日志打印导致程序崩溃的实战分析
在软件开发和运维中,日志记录是必不可少的一环,帮我们追踪程序的行为,定位问题所在。然而,有时日志本身却可能成为问题的根源。本文将通过一个真实的案例来探讨 Logback 日志系统中的一个常见问题,当并发量大ÿ…...
新加坡 Numen Cyber 与香港光环云数据有限公司达成战略合作
新加坡本土网络安全公司 Numen Cyber 宣布与香港光环云数据有限公司(简称“光环云香港”)建立战略合作伙伴关系。此次合作将重点放在云服务器和云服务业务场景的安全领域。 Numen Cyber,作为一家致力于为客户提供专业网络安全服务和一体化安…...
Laravel魔术方法:框架的隐秘力量
Laravel魔术方法:框架的隐秘力量 引言 Laravel是一个充满魔力的PHP框架,它通过许多巧妙的设计让Web开发变得简洁而优雅。在Laravel中,魔术方法(Magic Methods)是这些魔力的体现之一。魔术方法是PHP预定义的、可以在类…...
系统复习Java日志体系
一,我们采用硬编码体验一下几个使用比较多的日志 分别导入几种日志的 jar 包 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…...
网络管理linux命令
在Linux系统中,有许多常用的网络命令用于检查网络配置、诊断网络问题以及管理网络连接。以下是一些常用的网络命令及其简要说明: ifconfig 显示或配置网络接口。 ifconfigip 用于显示和操作路由、设备、策略路由和隧道。 ip addr show ip link show ip …...
PowerDNS架构解析与安装部署指南
1、背景介绍 目前公司使用PowerDNS进行DNS管理,但由于采用的是单节点架构,存在不可用的风险。为提升系统的稳定性和可靠性,我们计划对现有架构进行重构。通过引入高可用性设计,我们将优化系统架构,使其能够在故障情况…...
Ubuntu 20.04.6 安装 Elasticsearch
1.准备 -- 系统更新 sudo apt update sudo apt upgrade -- 安装vim 文本编辑器 sudo apt install vim-- jdk 版本确认 java -versionjdk 安装可以参照:https://blog.csdn.net/CsethCRM/article/details/140768670 2.官方下载Elasticsearch 官方地址:h…...
Python for循环迭代原理(迭代器 Iterator)
在使用Python时,我们经常会使用for循环来访问容器对象(列表、字符、字典等)中的元素。其幕后实际是通过迭代协议来完成的,迭代是一种依次访问对象中元素的方式,for循环在对象上调用iter()函数生成一个迭代器࿰…...
通信原理-思科实验四:静态路由项配置实验
实验四 静态路由项配置实验 一:实验内容 二:实验目的 三、实验原理 四、实验步骤 选择三个2811型号的路由器 R1、R2、R3 路由器默认只有两个快速以太网接口,为路由器R1和R3增加快速以太网接口模块NM-1FE-TX,安装后检查路由器的接…...
ngzero使用外部的svg图标
1.将图标svg下下来,放到项目中,路径如下所示 之后 <span nz-icon [nzIconfont]“‘icon-zhibiao’”>使用 2.直接使用阿里的图标 先将你要用的图标放入购物车,再将购物车的图标添加到你主页的我的项目中 之后代码中在startupService…...
逆矩阵、秩
在数学的广阔天地中,线性代数扮演着至关重要的角色。它不仅是现代科学和工程学的基石,也是理解复杂数据结构的关键。本文将深入探讨线性代数中的几个核心概念:逆矩阵、秩、列空间和零空间,通过详细的解释和丰富的实例,…...
pc端小程序抓包修改数据相关记录
看了很多关于小程序抓包的 废话不多说直接演示 一、小程序抓包 1.所需要的工具 官网下载即可: https://www.charlesproxy.com/latest-release/download.do 我这里用的 Charles-proxy-4.6.6-win64 需要中文破解参考 https://www.jianshu.com/p/4d67dbbf2f6a 2、破…...
用Python打造精彩动画与视频.2.1 Python基础语法概述
2.1 Python基础语法概述 Python作为一门功能强大且易于学习的编程语言,其基础语法简单直观,非常适合初学者入门。这一节将带你了解Python的基本语法规则,为后续制作动画和视频打下坚实的基础。 1. 变量与数据类型 Python的变量不需要提前声…...
Golang高效合并(拼接)多个gzip压缩文件
有时我们可能会遇到需要把多个 gzip 文件合并成单个 gzip 文件的场景,最简单最容易的方式是把每个gzip文件都先解压,然后合并成一个文件后再次进行压缩,最终得到我们想要的结果,但这种先解压后压缩的方式显然效率不高,…...
MySQL数据库-基本概念
数据 描述事物的符号记录包括属组、文字、图形、图像、声音、档案记录等以“记录”形式按统一的格式进行存储 表 将不同的记录组织在一起用来存储具体数据 数据库 表的集合,是以一定的组织方式存储的相互有关的数据集合 数据库管理系统(DBMS&#…...
【无标题】web+http协议+nginx搭建+nginx反向代理(环境准备)
一.Web 为用户提供互联网上浏览信息的服务,web服务是动态的,可交互的。 1.安装httpd yum -y install httpd 2.启动 systemctl start httpd 3.关闭防火墙 systemctl stop firewalld [rootrs html]# echo "我手机号是" > …...
c-periphery RS485串口库文档serial.md(serial.h)(非阻塞读)(VMIN、VTIME)
c-peripheryhttps://github.com/vsergeev/c-periphery 文章目录 NAMESYNOPSISENUMERATIONS关于奇偶校验枚举类型 DESCRIPTIONserial_new()serial_open()关于流控制软件流控制(XON/XOFF)硬件流控制(RTS/CTS)选择流控制方法 serial_…...
Matlab arrayfun 与 bsxfun——提高编程效率的利器!
许多人知道 MATLAB 向量化编程,少用 for 循环 可以提高代码运行效率,但关于代码紧凑化编程, arrayfun 与 bsxfun 两个重要函数却鲜有人能够用好,今天针对这两个函数举例说明其威力。 Matlab arrayfun 概述 arrayfun 是 Matlab …...
【Unity编辑器拓展】GraphView自定义可视化节点
1、创建节点区域脚本 其中的new class UxmlFactory,可以让该元素显示在UI Builder中,我们就可以在Library-Project中看到我们新建的这两个UI元素,就可以拖入我们的UI窗口编辑了 public class NodeTreeViewer : GraphView {public new class…...
教程系列4 | 趋动云『社区项目』极速体验 LivePortrait 人脸表情“移花接木”大法
LivePortrait LivePortrait 由快手可灵大模型团队开源,只需 1 张原图就能生成动态视频。 LivePortrait 的核心优势在于其卓越的表情"迁移"技术,能够令静态图像中的人物瞬间焕发活力,无论是眨眼、微笑还是转头,皆栩栩如…...
Qwen3-32B部署全攻略:3步搞定,零基础也能快速上手
Qwen3-32B部署全攻略:3步搞定,零基础也能快速上手 1. 为什么选择Qwen3-32B? Qwen3-32B是当前开源大模型领域的佼佼者,拥有320亿参数的强大能力。与市面上其他模型相比,它有三个突出优势: 推理能力卓越&a…...
AI 推理引擎的并行化实现
AI推理引擎的并行化实现:加速智能决策的关键 随着人工智能技术的快速发展,AI推理引擎已成为许多应用的核心组件,从自动驾驶到医疗诊断,再到智能客服,其高效性直接影响用户体验和系统性能。随着模型规模的扩大和实时性…...
大麦网抢票自动化工具:5分钟快速上手完整指南
大麦网抢票自动化工具:5分钟快速上手完整指南 【免费下载链接】damaihelper 支持大麦网,淘票票、缤玩岛等多个平台,演唱会演出抢票脚本 项目地址: https://gitcode.com/gh_mirrors/dam/damaihelper 你是否曾经因为抢不到心仪的演唱会门…...
告别慢查询:用快马ai智能生成postgresql性能优化与索引方案
告别慢查询:用快马AI智能生成PostgreSQL性能优化与索引方案 在电商系统中,订单查询是最常见的操作之一。随着业务量的增长,数据库查询性能往往会成为瓶颈。最近我在优化一个电商平台的订单查询模块时,发现几个典型的性能问题&…...
突破性能瓶颈:Rust如何重塑数据科学与AI的未来
突破性能瓶颈:Rust如何重塑数据科学与AI的未来 在当今数据驱动的时代,数据科学与AI领域正面临着前所未有的性能挑战。随着数据集规模的爆炸式增长和模型复杂度的不断提升,传统编程语言在处理高并发、大规模数据时逐渐显露出性能瓶颈。而Rust…...
实战演练:基于快马AI快速构建竞品价格监控爬虫系统
今天想和大家分享一个非常实用的爬虫实战项目——竞品价格监控系统。这个系统可以帮助我们实时跟踪不同电商平台上同类产品的价格变化,对于市场调研、价格策略制定都很有帮助。下面我会详细介绍整个实现过程,以及我在使用InsCode(快马)平台时的一些体验。…...
零基础入门机器人抓取:在快马平台轻松搞定龙虾openclaw安装与第一个程序
最近在学习机器人抓取相关的知识,发现龙虾openclaw是个不错的入门工具。作为一个完全零基础的小白,我在安装和配置环境时遇到了不少困难。好在发现了InsCode(快马)平台,它帮我轻松解决了这些问题。下面分享一下我的学习过程。 了解openclaw …...
Homebox开发者手册:从源码构建到自定义扩展的完整教程
Homebox开发者手册:从源码构建到自定义扩展的完整教程 【免费下载链接】homebox Homebox is the inventory and organization system built for the Home User 项目地址: https://gitcode.com/gh_mirrors/ho/homebox Homebox是一款为家庭用户打造的库存和组织…...
快速构建tomcat配置可视化原型:用快马一键生成配置向导界面
今天想和大家分享一个快速验证Tomcat配置方案的小技巧。作为一个Java开发者,经常需要折腾Tomcat的安装配置,每次都要重复下载、配环境变量、改server.xml这些步骤,特别耗时。最近发现用InsCode(快马)平台可以快速生成一个可视化配置向导&…...
如何通过4个步骤让百度网盘下载速度提升30倍?
如何通过4个步骤让百度网盘下载速度提升30倍? 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘几十KB的下载速度而焦虑吗?百度网盘直链解…...
