SpringBoot线上服务假死解决,CPU内存正常

news2024/11/26 3:52:04

背景

开发小伙伴都知道线上服务挂掉,基本都是因为cpu或者内存不足,出现GC频繁OOM之类的情况。本篇文章区别以上的情况给小伙伴们
带来不一样的服务挂掉。

还记得哔哩哔哩713事故中那场诡计多端的0吗?
在这里插入图片描述
对就是这个0,和本次事故没关系,但三省同学深受学习。
相关阅读:
2021.07.13 我们是这样崩的
线上服务假死解决
IDEA插件JProfiler安装使用 
Tomcat10下载安装及各个线程作用详解

问题排查

老规矩在集群环境中同一个服务几个节点无响应。如不及时解决会可能形成雪崩效应。
优先查看服务日志是否有报错,礼貌习惯性查看服务cpu及内存情况。先复习下,若服务无报错。cpu或内存出现异常,按如下步骤排查。

常规排查

1、查看服务进程中线程情况

top -H -p pid
或
ps -mp pid -o THREAD,tid,time

2、查看系统异常线程16进制

printf “%x\n” nid

3、查看异常线程堆栈信息

jstack pid | grep number

查看占用最大内存对象前一百

jmap -histo pid|head -100

导出到文件

jstack -l PID >> a.log

或dump信息使用工具Mat或JProfiler查看

jmap -dump:live,format=b,file=/dump.bin pid

经过上面一通手法操作,足以解决此类常规报错了,通常大多是原因各种循环递归、或数据库慢查询等。

Mat使用

在MAT中,会有两种大小表示:

Shallow Size:表示对象自身占用的内存大小,不包括它引用的对象。
Retained size:当前对象内存大小+当前对象直接或间接引用的对象大小,全部的总和,简单理解,就是当前对象被GC后,总共能释放的内存大小。

Histogram视图

以Class Name为维度,分别展示各个类的对象数量。它默认是以byte为单位的,

请添加图片描述

要显示让单位展示出来,点击Window->Preferences选择最后一项,点击Apply and Close
再重新打开Histogram视图,就会生效了。
请添加图片描述

Leak Suspects

报表很直观地展现了一个饼图,图中颜色深的部分表示可能存在内存泄漏的嫌疑。

通过这个指标可以快速定位内存泄漏地方出现在哪个类方法里的哪行代码。

本次问题排查

1、 信息收集分析

因服务健康监测无响应,cpu及内存情况正常,直接查看堆栈信息,看看线程都在干什么

jstack -l PID >> a.log

Jstack的输出中,Java线程状态主要是以下几种:

RUNNABLE 线程运行中或I/O等待

BLOCKED 线程在等待monitor锁(synchronized关键字)

TIMED_WAITING 线程在等待唤醒,但设置了时限

WAITING 线程在无限等待唤醒

发现都是WAITING线程。

"http-nio-8888-exec-6666" #8833 daemon prio=5 os_prio=0 tid=0x00001f2f0016e100 nid=0x667d waiting on condition [0x00002f1de3c5200]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00000007156a29c8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1897)
at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1458)
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1253)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4619)
at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:680)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4615)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1231)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1223)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:90)
at com.baomidou.dynamic.datasource.ds.ItemDataSource.getConnection(ItemDataSource.java:56)
at com.baomidou.dynamic.datasource.ds.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:48)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:82)
at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:68)
at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:336)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:84)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:143)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy571.query(Unknown Source)

2、定位关键信息,追踪源代码

  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
  at com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1897)
  DruidConnectionHolder takeLast() throws InterruptedException, SQLException {
  try {
  while (poolingCount == 0) {
  emptySignal(); // send signal to CreateThread create connection

                if (failFast && isFailContinuous()) {
                    throw new DataSourceNotAvailableException(createError);
                }

                notEmptyWaitThreadCount++;
                if (notEmptyWaitThreadCount > notEmptyWaitThreadPeak) {
                    notEmptyWaitThreadPeak = notEmptyWaitThreadCount;
                }
                try {
                    // 数据库的连接都没有释放且被占用,连接池中无可用连接,导致请求被阻塞
                    notEmpty.await(); // signal by recycle or creator
                } finally {
                    notEmptyWaitThreadCount--;
                }
                notEmptyWaitCount++;

                if (!enable) {
                    connectErrorCountUpdater.incrementAndGet(this);
                    throw new DataSourceDisableException();
                }
            }
        } catch (InterruptedException ie) {
            notEmpty.signal(); // propagate to non-interrupted thread
            notEmptySignalCount++;
            throw ie;
        }

        decrementPoolingCount();
        DruidConnectionHolder last = connections[poolingCount];
        connections[poolingCount] = null;

        return last;
  }

结合日志报错定位到问题代码。因报错可用连接没有正常释放,导致一直await卡死。
问题代码如下:

  try {
	  SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
	  TestMapper mapper = sqlSession.getMapper(TestMapper.class);
	  mapper.insetList(list);
	  sqlSession.flushStatements();
  } catch (Exception e) {
  	  e.printStackTrace();
  }

问题复现

按照以上信息在多活环境复现。因线程被打满且都在等待导致监控检查无响应。

tomcat线程被打满:
在这里插入图片描述

tomcat默认参数:

最大工作线程数,默认200。
server.tomcat.max-threads=200
最大连接数默认是10000
server.tomcat.max-connections=10000
等待队列长度,默认100。
server.tomcat.accept-count=100

最小工作空闲线程数,默认10。
server.tomcat.min-spare-threads=100

Druid连接池的默认参数如下:
请添加图片描述
Druid连接池的配置参数如下:

属性说明建议值
username登录数据库的用户名
password登录数据库的用户密码
initialSize默认0,启动程序时,在连接池中初始化多少个连接10-50足够
maxActive默认8,连接池中最多支持多少个活动会话
maxWait默认-1,程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池, 没有可用连接,单位毫秒,设置-1时表示无限等待100
minEvictableIdleTimeMillis池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将回收该连接,要小于防火墙超时设置 net.netfilter.nf_conntrack_tcp_timeout_established见说明部分
timeBetweenEvictionRunsMillis 检查空闲连接的频率,单位毫秒, 非正整数时表示不进行检查
keepAlive程序没有close连接且空闲时长超过 minEvictableIdleTimeMillis,则会执 行validationQuery指定的SQL,以保证该程序连接不会池kill掉,其范围不超过minIdle指定的连接个数true
minIdle默认8,回收空闲连接时,将保证至少有minIdle个连接.与initialSize相同
removeAbandoned要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。false,当发现程序有未正常close连接时设置为true
removeAbandonedTimeout设置druid 强制回收连接的时限,当程序从池中get到连接开始算起,超过此 值后,druid将强制回收该连接,单位秒。应大于业务运行最长时间
logAbandoned当druid强制回收连接后,是否将stack trace 记录到日志中true
testWhileIdle当程序请求连接,池在分配连接时,是否先检查该连接是否有效。(高效)true
validationQuery检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果 正常返回,则表示连接可用,否则表示连接不可用
testOnBorrow程序申请连接时,进行连接有效性检查(低效,影响性能)false
testOnReturn程序返还连接时,进行连接有效性检查(低效,影响性能)false
poolPreparedStatements缓存通过以下两个方法发起的SQL: public PreparedStatement prepareStatement(String sql) public PreparedStatement prepareStatement(String sql,int resultSetType, int resultSetConcurrency)true
maxPoolPrepareStatementPerConnectionSize每个连接最多缓存多少个SQL20
filters这里配置的是插件,常用的插件有:监控统计: filter:stat 日志监控: filter:log4j 或者 slf4j 防御SQL注入: filter:wallstat,wall,slf4j
connectProperties连接属性。比如设置一些连接池统计方面的配置。 druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 比如设置一些数据库连接属性

解决

1、Druid连接池的配置超时参数

spring: 
  redis:
    host: localhost
    port: 6379
    password: 
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 5
        min-idle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,slf4j,wall
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000

2、异常及时关闭连接

sqlSession.close();

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

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

相关文章

Python基础知识入门(二)

Python基础知识入门&#xff08;一&#xff09; 一、数字类型 Python 数字数据类型用于存储数值。数据类型是不允许改变的&#xff0c;如改变数字数据类型的值&#xff0c;将重新分配内存空间。 1.数字函数 函数 描述 abs(x) 返回数字的绝对值。如abs(-10) 返回 10。 fa…

前端小游戏——推箱子

最近刚刚更新完了HTML&#xff0c;CSS的万字总结&#xff0c;有很多人已经学习完了文章&#xff0c;感觉反馈还不错&#xff0c;今天&#xff0c;用HTML&#xff0c;CSS&#xff0c;JS的知识编写了一个童年经典游戏 - 推箱子&#xff0c;供学习参考。 推荐学习专栏&#xff1a…

EdrawMax Ultimate v12.0 图表和流程图

EDraw Max 是一个多合一的应用程序&#xff0c;用作演示构建器、图表创建者、可视化业务规划师和协作空间&#xff08;用于快速共享图表和模型并接收反馈&#xff09;。 该软件可用于哪些潜在用途&#xff1f; 任何人都可以从 EDraw Max 中受益。它所针对的主题和感兴趣的领域…

【EasyRL学习笔记】第十一章 模仿学习

文章目录一、前言二、行为克隆三、逆强化学习四、第三人称视角模仿学习五、序列生成和聊天机器人六、关键词总结七、习题一、前言 模仿学习 (imitation learning&#xff0c;IL) 讨论的问题是&#xff0c;假设我们连奖励都没有&#xff0c;要怎么进行更新以及让智能体与环境交…

黑马学Docker(二)

目录&#xff1a; &#xff08;1&#xff09;容器命令介绍 &#xff08;2&#xff09; 容器命令案例1 &#xff08;3&#xff09;容器命令案例2 &#xff08;4&#xff09;容器命令练习 &#xff08;5&#xff09;数据卷命令 &#xff08;6&#xff09; 数据卷挂在案例1 …

数字孪生:实现保险行业数字化转型

现如今&#xff0c;数据分析在各个行业都在广泛的使用&#xff0c;保险行业也不例外。在数字化浪潮席卷全球的时代&#xff0c;如何利用数字化技术驱动业务增长&#xff0c;实现数字化转型&#xff0c;是目前保险行业需要思考的问题。 可视化技术能够助力保险机构更好地解决互联…

[hive]维度模型分类:星型模型,雪花模型,星座模型|范式|纬度建模|数仓分层

数仓&#xff08;十八&#xff09;数仓建模以及分层总结(ODS、DIM、DWD、DWS、DWT、ADS层) - 墨天轮 一、维度模型分类:星型模型,雪花模型,星座模型 1、星型模型 星型模型中只有一张事实表&#xff0c;以及0张或多张维度表&#xff0c;事实与纬度表通过主键外键相关联&#…

vue项目 API接口封装

vue项目 API接口封装 01.基础配置创建 分别创建如下文件和文件夹 Object │ .env.development │ .env.production └─src├─api│ index.js│ login.js├─utils│ request.js.env.development 和 .env.production 配置生产环境和开发环境移步&#xf…

Java程序员不得不会的124道面试题(含答案)

1&#xff09;Java 中能创建 volatile 数组吗&#xff1f; 能&#xff0c;Java 中可以创建 volatile 类型数组&#xff0c;不过只是一个指向数组的引用&#xff0c;而不是整个数组。我的意思是&#xff0c;如果改变引用指向的数组&#xff0c;将会受到 volatile 的保护&#x…

多线程常见锁的策略

文章目录前言一、乐观锁和悲观锁1.1 定义1.2 生动有趣滴例子1.3 版本号机制二、读写锁2.1 读写锁的由来2.2 生动有趣de例子2.3 ReentrantReadWriteLock 类三、重量级锁与轻量级锁3.1 定义3.2 生动活泼の例子3.3 自旋锁&#xff08;Spin Lock&#xff09;四、公平锁与非公平锁五…

一名程序员的电脑桌面

配置&#xff1a; 酷呆桌面注册表隐藏快捷方式箭头图标开启桌面模式自动隐藏任务栏 酷呆桌面 在选择酷呆之前&#xff0c;一直是使用的Fences&#xff0c;他的桌面切换功能非常赞&#xff0c;适合划分工作区。但由于强迫症实在是忍受不了肉眼可见的掉帧、黑背景bug&#xff0…

简简单单搞一个实用的Android端搜索框

Hello啊老铁们&#xff0c;今天带来一个非常实用的自定义搜索框&#xff0c;包含了搜索框、热门搜索列表、最近搜索列表等常见的功能&#xff0c;有类似的&#xff0c;大家可以直接复用&#xff0c;将会大大节约您的开发时间&#xff0c;有一点&#xff0c;很负责任的告诉大家&…

最全面的Mybatis教程,从“开局”到“通关”,Ready Go!

前言 本文为SSM框架 【Mybatis】 相关知识&#xff0c;MyBatis 是一款优秀的半自动的ORM持久层框架&#xff0c;下边将对Mybatis的简介、Mybatis的CRUD实现&#xff0c;Mybatis的配置文件&#xff0c;Mybatis的日志配置&#xff0c;resultMap详解&#xff0c;分页实现&#xff…

Vulnhub_CengBox

目录 一 环境异常处理 &#xff08;一&#xff09;nat设置无法正常获取地址 1 单用户模式进入命令行 2 passwd更改 3 修改网络配置文件 二 环境测试 &#xff08;一&#xff09;信息收集 1 端口服务 2 目录扫描 &#xff08;二&#xff09;漏洞测试 1 SQL…

SpringBoot项目的创建(一):通过idea的Spring Initializr来创建(需联网以下载SpringBoot相关的模板)

SpringBoot项目的创建1. 环境准备2. 创建SpringBoot项目3. 创建的SpringBoot项目结构如下4. 添加代码测试web页面效果1. 环境准备 安装jdk和idea&#xff0c;tomcat可不安装&#xff0c;有内置的tomcat 2. 创建SpringBoot项目 打包成war后&#xff0c;需要部署到tomcat中再运…

大数据培训技术操作Flume测试监控

大数据培训技术操作Flume测试监控 1&#xff09;修改/opt/module/flume/conf目录下的flume-env.sh配置&#xff1a; JAVA_OPTS”-Dflume.monitoring.typeganglia -Dflume.monitoring.hosts192.168.9.102:8649 -Xms100m -Xmx200m” 2&#xff09;启动Flume任务 [atguiguh…

关于微前端,你理解到究极奥义了么?

微前端的起源 在微前端这个概念出现之前&#xff0c;我们或多或少都能够联想到另一个词性上有些相似的概念微服务&#xff0c;它从出现后便一直都很火热&#xff0c;并不断催生着后端架构体系的演进&#xff0c;而此刻我们如果细品一下这微字头的两兄弟&#xff0c;探究他们的诞…

大白鲨优化算法(WSO)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

2022年Java发展怎么样?现在学了Java技术出来是否还能找到工作?

马云爸爸说过&#xff0c;未来的制造业要的不是石油&#xff0c;最大的能源应该是数据。不管你是上网购物&#xff0c;还是手机浏览咨询&#xff0c;甚至是政府机构&#xff0c;大型跨国集团系统&#xff0c;银行&#xff0c;背后的庞大的数据处理都是由Java来完成&#xff0c;…

FPGA时序约束02——不同时序路径的分析方法

前言前文&#xff08;FPGA时序约束01——基本概念&#xff09;中介绍了四种时序路径&#xff0c;如下图所示。 分别是触发器到触发器&#xff0c;触发器到输出端&#xff0c;输入端到触发器&#xff0c;输入端到输出端&#xff0c;其中输入端到输出端是纯组合逻辑路径&#xff…