FullGC频繁,线程数持续增长排查

news2024/11/26 22:23:57

告警

线上应用fullgc频繁,收到告警

GC监控—堆内存不足

查看近12小时的监控,发现Survivor区一直处于 满状态、fullgc非常频繁、但没有内存溢出的现象,很明显是堆内存不足
在这里插入图片描述

GC日志分析—暂停时间并不长

因为fullgc相当频繁,抽取了一次fullgc日志分析,发现一次fullgc过程中,暂停时间并不长
例如下面的fullgc,暂停时长为

  • 初始标记CMS-initial-mark:0.05s
  • 重新标记CMS Final Remark:0.29s
2022-11-22T09:11:30.438+0800: 344102.892: [GC (Allocation Failure) 2022-11-22T09:11:30.440+0800: 344102.894: [ParNew: 1376182K->153600K(1382400K), 0.2052663 secs] 3454603K->2289
346K(4040704K), 0.2088212 secs] [Times: user=0.56 sys=0.01, real=0.21 secs]
2022-11-22T09:11:30.662+0800: 344103.116: [GC (CMS Initial Mark) [1 CMS-initial-mark: 2135746K(2658304K)] 2310318K(4040704K), 0.0489591 secs] [Times: user=0.13 sys=0.01, real=0.
05 secs]
2022-11-22T09:11:30.716+0800: 344103.170: [CMS-concurrent-mark-start]
2022-11-22T09:11:31.347+0800: 344103.801: [CMS-concurrent-mark: 0.631/0.631 secs] [Times: user=1.29 sys=0.03, real=0.64 secs]
2022-11-22T09:11:31.351+0800: 344103.805: [CMS-concurrent-preclean-start]
2022-11-22T09:11:31.366+0800: 344103.819: [CMS-concurrent-preclean: 0.014/0.015 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
2022-11-22T09:11:31.369+0800: 344103.823: [CMS-concurrent-abortable-preclean-start]
2022-11-22T09:11:31.533+0800: 344103.987: [GC (Allocation Failure) 2022-11-22T09:11:31.535+0800: 344103.989: [ParNew: 1382400K->153600K(1382400K), 0.2068298 secs] 3518146K->2345
666K(4040704K), 0.2097398 secs] [Times: user=0.58 sys=0.01, real=0.21 secs]
2022-11-22T09:11:32.654+0800: 344105.108: [CMS-concurrent-abortable-preclean: 1.058/1.285 secs] [Times: user=2.70 sys=0.04, real=1.28 secs]
2022-11-22T09:11:32.667+0800: 344105.121: [GC (CMS Final Remark) [YG occupancy: 1345792 K (1382400 K)]2022-11-22T09:11:32.668+0800: 344105.122: [Rescan (parallel) , 0.1862920 se
cs]2022-11-22T09:11:32.854+0800: 344105.308: [weak refs processing, 0.0001122 secs]2022-11-22T09:11:32.854+0800: 344105.308: [class unloading, 0.0624232 secs]2022-11-22T09:11:32
.917+0800: 344105.371: [scrub symbol table, 0.0319926 secs]2022-11-22T09:11:32.949+0800: 344105.403: [scrub string table, 0.0032403 secs][1 CMS-remark: 2192066K(2658304K)] 35378
59K(4040704K), 0.2851247 secs] [Times: user=0.65 sys=0.01, real=0.29 secs]
2022-11-22T09:11:32.958+0800: 344105.412: [CMS-concurrent-sweep-start]
2022-11-22T09:11:33.030+0800: 344105.483: [GC (Allocation Failure) 2022-11-22T09:11:33.031+0800: 344105.485: [ParNew: 1382400K->120109K(1382400K), 0.1535558 secs] 3550502K->2343
198K(4040704K), 0.1567270 secs] [Times: user=0.42 sys=0.01, real=0.15 secs]
2022-11-22T09:11:34.931+0800: 344107.384: [CMS-concurrent-sweep: 1.771/1.972 secs] [Times: user=3.94 sys=0.06, real=1.98 secs]
2022-11-22T09:11:34.933+0800: 344107.387: [CMS-concurrent-reset-start]
2022-11-22T09:11:34.942+0800: 344107.396: [CMS-concurrent-reset: 0.009/0.009 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

Thread监控—线程数持续增长

另一个同学注意到线程监控异常,发现线程数持续增长,处于TIMED_WATING状态的线程也持续增长,
初步怀疑是线程对象较多,且状态处于长时间的TIMED_WATING,所以younggc无法回收,进入老年代,引起频繁fullgc
在这里插入图片描述

执行jstack—分析线程

线上执行jstack

使用工具IBM Thread and Monitor Dump Analyzer for Java (TMDA)对stack日志进行分析

线程状态分析

发现

  • 线程总数多,6k+
  • 91%的线程在等待,Wating on condition,看堆栈,是调用了Thread.sleep

在这里插入图片描述

Waiting on condition线程分析

查看状态为Waiting on condition状态的线程,发现几乎都是Druid-ConnectionPool-Destory-xxxx
在这里插入图片描述

线程堆栈信息
在这里插入图片描述

分析Druid-ConnectionPool-Destory线程

DruidDataSource.init()
->createAndStartDestroyThread()
相关代码如下

        String threadName = "Druid-ConnectionPool-Destroy-" + System.identityHashCode(this);
        destroyConnectionThread = new DestroyConnectionThread(threadName);
        destroyConnectionThread.start();

也就是说,一个DruidDataSource连接池,对应一个Druid-ConnectionPool-Destroy线程
上面的6k左右个Druid-ConnectionPool-Destroy线程,对应了6k左右的DruidDataSource连接池🥶

所以,究竟是哪里创建了这么多连接池?

哪里创建了这么多连接池?

这个应用是bi系统中的数据查询引擎,维护了很多库,约500个,但现在有6k左右的数据库连接池肯定是不对劲的。
后来经过排查,是有个定时检查内存中的连接池与数据库中维护的数据源信息差异的任务,在不断的创建连接池,在某个分支条件下,创建了连接池后,发生异常,但没有及时关闭连接池,导致在后续的定时任务调度中,不断的创建连接池。

结论与方案

关于连接池

对于连接池的维护,部分代码需要优化,尤其是在发生异常时,没有及时关闭连接池。这也是本次告警的主要原因

关于gc

从上面的排查来看gc频繁的问题,应该就是因为数据库连接池频繁创建,没有及时关闭造成的。
但gc日志分析来看gc暂停时间并不长,只是gc整个过程较长
●新生代的s区基本处于满状态,fullgc频繁,但没有内存泄露的现象,很明显是内存不足
●抽取一次fullgc日志分析,发现gc暂停时间不长,是运维告警的问题

若有收获,就点个赞吧

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目管理(知识体系概述)

项目的定义:为创造独特的产品、服务或者成果进行的临时性工作。 项目的特性:1、独特的产品、服务、成果;2、临时性工作。 项目管理的目的(为了解决什么问题): 1、达成业务目标 2、满足相关方期望 3、提供项目的可预测性 4、提高项目的成果性。 5、在适当的时刻交付…

机器人运动学标定:基于考虑约束的指数积的运动学标定方法——只需要测量位置,避免冗余约束

文章目录写在前面为什么要消除归一化和正交化操作?只用位置而不是位姿去做标定的原因基于消除冗余约束步骤的参数辨识模型分析参考文献写在前面 基于指数积的运动学标定方法介绍: 机器人运动学标定:基于指数积的串联机构运动学标定 机器人运…

Vue表单修饰符:v-model.lazy、v-model.number、v-model.trim

表单修饰符有:lazy、number、trim;修饰符加在v-model后面; lazy修饰符: v-model的作用是双向绑定表单,能获取到input输入框的值,而且是实时获取的,就是当你输入框里的值发生改变就会获取到&…

【Shell 脚本速成】02、Shell 变量详解

目录 一、变量介绍 变量存取原理 二、变量定义 2.1 什么时候需要定义变量? 2.2 定义一个变量 定义变量举例: 定义变量演示: 2.3 取消变量 unset 2.4 有类型变量 declare declare 命令参数: 案例演示: 三…

向前迈进!走入GC世界:G1 GC原理深入解析

第零章:名词解释 mutator:应用线程 STW:Stop-The-World,指除了GC线程,其它所有线程全部暂停的一段时间 并发:指代GC线程与mutator在同一时刻执行任务 并行:指代多个GC线程在同一时刻执行任务…

一站式元数据治理平台——Datahub

一站式元数据治理平台——Datahub万字保姆级长文——Linkedin元数据管理平台Datahub离线安装指南 - 独孤风 - 博客园 (cnblogs.com)企业级数据治理工作怎么开展?Datahub这样做 - 独孤风 - 博客园 (cnblogs.com)【DataHub】 现代数据栈的元数据平台–如何与spark集成…

如何设计金融机构多场景关键应用下的存储架构

【摘要】银行、保险等金融机构存在多场景下的关键应用,如何选择适合各场景下的存储,如何设计适合业务的存储架构,显得尤为重要。本文从当前主流存储架构分析入手,提出金融机构业务场景分析与架构选型思路,以Glusterfs为例,分享如何根据业务场景的特点,有针对性的选取适合…

SQL优化

文章目录提升group by的效率分页查询优化覆盖索引子查询起始位置重定义检查 where,order by,group by后面的列尽量使用 varchar 代替 char。(SQL 性能优化)如果修改 / 更新数据过多,考虑批量进行提升group by的效率 select user_id,user_nam…

spring-security源码学习总结

由于SpringBoot 对 Security 的支持类均位于org.springframework.boot.autoconfigure.security包下,主要通过 SecurityAutoConfiguration 自动配置类和 SecurityProperties 属性配置来完成,所以需要下载springboot源码深入学习 SecurityAutoConfiguratio…

云原生边缘设备解决方案Akri on k3s初体验

作者: 涂家英,SUSE 资深架构师,专注 Cloud-Native 相关产品和解决方案设计,在企业级云原生平台建设领域拥有丰富的经验。 写在前面 k3s 是 SUSE 推出的为物联网和边缘计算构建的经过认证的 Kubernetes 发行版,它可以帮…

指数函数及其导函数

目录前言指数函数的导函数指数函数导函数动图绘制参考文献前言 前面我们介绍了指数函数及其基本性质以及如何在笛卡尔直角坐标系下绘制静态的指数函数图像,这一节,我们将重点讨论一下指数函数的导函数以及导函数的动态表示,为方便起见&#…

大数据(9f)Flink富函数RichFunction

文章目录1、概述2、示例2.1、普通函数2.2、富函数2.2.1、获取富函数的运行时上下文3、源码截取3.1、RichFunction3.2、RuntimeContext1、概述 Rich Function,译名富函数,和普通函数相比,多了:生命周期(open和close方法…

DGL学习笔记——第二章 消息传递范式

提示:DGL用户指南学习中 文章目录一、内置函数和消息传递API二、编写高效的消息传递代码总结消息传递是实现GNN的一种通用框架和编程范式。它从聚合与更新的角度归纳总结了多种GNN模型的实现。 假设节点 𝑣 上的的特征为 𝑥𝑣∈ℝ…

Java(八)----多线程

1. 线程的基本概念 1.1 进程 任何的软件存储在磁盘(硬盘)中,运行软件的时候,OS(操作系统)使用IO技术,将磁盘中的软件的文件加载到内存,程序才能运行。 (进程是从硬盘到内存) 进程的概念 : 应…

Marked.js让您的文档编辑更加轻松自如!

低代码应用平台——kintone既可以保留更改记录,也有流程管理的功能,在公司内部分享会议记录啊、wiki等文档或学习资料等时非常的便利。 kintone还有丰富的文本编辑框,可以对内容进行编辑提高易读性。但是还是有不少人觉得如果能够使用Markdo…

19.[Python GUI] PyQt5中的模型与视图框架-基本原理

PyQt中的模型与视图框架 一、Qt中模型与视图相关的类 二、模型与视图的基本原理 MVC把图形界面分为三个部分:模型(Model),视图(View)和控制器(Controller), 模型&#x…

Git大型文件存储

什么是 Git LFS? Git 是跟踪代码库演变和与同行高效协作的绝佳选择。但是,当您要跟踪的存储库非常大时会发生什么? 如果您考虑一下,存储库变得庞大的主要原因大致有两个: 他们积累了非常非常长的历史(项目…

【C】文件操作fopen与fclose

目录 函数 1.fopen 2.fclose 3.freopen 函数 头文件 #include<stdio.h> 1.fopen FILE *fopen(const char *restrict dilename,const char* restrict mode); 作用&#xff1a;打开文件参数&#xff1a; 第一个是含有要打开文件名的字符串&#xff08;"文件名…

肝了一周的八万字Redis实战篇

Redis实战篇 文章目录Redis实战篇开篇导读1. 短信登录2. 商户查询缓存3. 优惠卷秒杀4. 附近的商户5. UV统计6. 用户签到7. 好友关注8. 达人探店一、短信登录1. 导入黑马点评项目1.1 导入SQL1.2 有关当前模型1.3 导入后端项目1.4 导入前端工程1.5 运行前端项目2. 基于Session实现…

【杂谈】快来看看如何使用LGMT这样的蜜汁缩写来进行CodeReview吧!

文章目录一、先从一个梗开始说起吧&#xff01;二、什么是LGTM&#xff1f;2.1 LGTM 是什么意思&#xff1f;2.2 蹭梗品牌故事2.3 虚假的CodeReview三、Code Review中的蜜汁缩写四、参考链接一、先从一个梗开始说起吧&#xff01; 公司最近在如火如荼的开展CodeReview活动&…