Java后端问题排查经验

线上出现问题首先应该做什么,不是解决问题,而是先恢复系统,把损失降到最小,有机会的话保留日志等数据用于后期问题复盘分析。解决问题可以后期慢慢复现排查,而线上用户的体验则不能多耽误一分一秒,任何线上问题的解决都应以用户为主。

出现问题的解决方法:重启,扩容,回滚,降级,限流

高并发高流量系统的设计处理:缓存,降级,限流

1. GC问题

  1. 收到预警后查看JVM监控,确定问题的时间点,内存,FGC频率,CPU使用率,线程数等。 如果频率规律,内存起伏正常,初步排除内存泄漏。
  2. 了解该时间点之前有没有上线,升级等操作,初步确定范围。
  3. 了解JVM的参数设置是否合理。
  4. 导出需要的堆栈文件,条件可以的话,也可以使用jmap,jstack等基本命令。
  5. 针对大对象或者长生命周期对象导致的FGC,可通过 jmap -histo 命令并结合dump堆内存文件作分析, 定位到可疑对象,通过可疑对象定位到具体代码再次分析。
  6. CPU使用率高 , top命令查询cpu使用率高的进程, top -Hp pid 定位进程中高使用率线程, jstack tid获 取栈信息,如果垃圾回收线程(VM Thread) ,说明GC导致cpu使用率高,问题在GC上,如果不是可以定位runnable中业务线程是否有死循环出现或者耗时计算(正常情况会出现我们工程相关代码)
  7. Full GC 次数过多,如果没有大对象产生,判断一下是不是有显示调用System.gc()的记录。
  8. Full GC 不多,CPU使用率不高,系统慢,分析jstack获取栈信息中如下关键字( Deadlock 死锁, waiting for monitor entry 等待获取锁,waiting on condition 等待某个资源或条件,in Object.wait),定位到具体代码行优化处理。
  9. 对于一些阻塞性的操作,这种操作不一定每次都能复现,可以通过压力测试的方式,放大阻塞效果, 定位阻塞点

2. 慢查询优化

  1. 先运行看看是否真的很慢,注意设置SQL_NO_CACHE
  2. where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高
  3. explain查看执行计划,是否与2预期一致(从锁定记录较少的表开始查询)
  4. order by limit 形式的sql语句让排序的表优先查
  5. 了解业务方使用场景
  6. 加索引时参照建索引的几大原则
  7. 观察结果,不符合预期继续从1分析

3. 内存使用率报警

3.1 内存泄漏问题-fastJson使用不当导致的内存泄漏

2020-05-31 20:40左右我这边收到任务服务告警:内存使用率超过75%

同时查看任务服务ump监控,tp99出现极值,高达17秒

紧接着查看JVM监控,发现在20:40触发了一次Full GC,而这次Full GC执行长达十几秒,故tp99出现极值是FullGC导致。

继续观察GC后堆内存使用情况,发现无论Young GC还是Full GC执行后仍让留有3个G的堆内存,而且每次都是堆内存即将打满后触发的GC,可以说GC执行的“很不顺利”。问题暴露后,为不影响接口性能及线上服务,暂时先将容器重启了,堆内存被重置。

持续观察线上服务内存

观察近期内存使用率情况(时间跨度为一个月),发现随着时间的推移,即使有GC,内存使用率依然逐步增高,早晚会触发下一次内存告警

观察近期GC情况,发现随着时间的推移,Yong GC后剩余堆内存在逐步递增,如下图

6月10左右,GC后剩余堆内存在300M左右

10天后,6月20日GC后剩余堆内存普遍在1.7个G,即随着时间推移GC后剩余的堆内存越来越多

问题定位
  1. 查看JVM参数配置

年轻代:Eden区(1879M) + S0(85M) + S1(84M) = 2048M

老年代:3072M

垃圾收集器用的是Java8默认的注重吞吐量的并行收集器

  1. 利用MAT工具查看堆内存对象使用情况

(a)首先找到java进程ID

(b)利用jmap命令,打印dump二进制日志

jmap -dump:format=b,file=/export/Logs/Domains/union-content- api.jd.local/server1/logs/dump.log <pid>

将dump日志输出到日志目录,再利用jdos的容器目录查询将日志下载下来(日志比较大,压缩后再下载)

(c)利用MAT工具查看堆内存使用情况

MAT(Memory Analyzer Tool),是一个java堆内存分析工具,可有效帮助我们排查内存泄漏问题

前面dump日志有4个G。。。 因日志过大,需要修改MAT的MemoryAnalyzer.ini配置文件:-Xmx5120m,否则无法分析

MAT工具导入dump日志分析后发现:fastJson的IdentityHashMap的Entry数组占用了绝大部分堆内存。

查看IdentityHashMap源码,是一个线性探测模式一个简单的Hash表,只不过他的key是由System.identityHashCode(key)生成,即一个对象对应一个唯一key且与对象的HashCode方法不同,无法被重写。

百度查fastJosn的IdentityHashMap内存泄漏相关资料,发现有很多类似问题

比如这篇文章:https://www.cnblogs.com/liqipeng/p/11665889.html

通过博客及源码发现,fastjson在处理泛型的反序列化时,ParserConfig类会反对序列化的目标类的泛型对象做缓存,而缓存容器正是IdentityHashMap,key则是反射包里的type对象.

说到fastjson处理泛型的反解析,一下子就想到任务服务的redis缓存优化,正是4月份上线的功能

下面这段代码是程序中触发内存泄漏的代码,它主要是将从redis取出的json字符串反解析成带泛型的java对象。

每次反解析都会实例化ParameterizedType对象,ParameterizedType继承自Type接口,

在JSONObject.parseObject方法中,ParameterizedType对象会被作为Map的key缓存在IdentityHashMap中,故随着这段代码调用次数的增加,越来越多的对象被实例化并被IdentityHashMap缓存起来而不被GC释放,故内存使用率越来越高。

参考https://github.com/alibaba/fastjson/issues/1418以及TypeReference的用法

修改为,或者将ParameterizedType对象做缓存也行

参考资料

【MAT工具使用介绍】java学习-【转】使用Eclipse MAT查找内存泄漏工具介绍_invalid hprof file header. (java.io.ioexception)-CSDN博客

【fastjson反序列化使用不当导致内存泄露】 https://www.cnblogs.com/liqipeng/p/11665889.html

【“com.alibaba.fastjson”遇到的内存泄漏问题】“com.alibaba.fastjson”遇到的内存泄漏问题 - 简书

【GitHub-Issue:parseObject是否存在内存泄漏情况】https://github.com/alibaba/fastjson/issues/1418

【GitHub-Wiki:TypeReference使用】https://github.com/alibaba/fastjson/wiki/TypeReference

netty在recyler使用FastThreadLocalThread内存溢出

由于内存的 allocate 和 release 不再同一个线程,造成的内存泄漏。

https://www.cnblogs.com/405845829qq/p/6255931.html

3.2 内存泄漏问题-从ThreadLocalMap分析ThreadLocal使用不当导致内存泄漏

首先我们先看看ThreadLocalMap的类图,在前面的介绍中,我们知道ThreadLocal只是一个工具类,他为用户提供get、set、remove接口操作实际存放本地变量的threadLocals(调用线程的成员变量),也知道threadLocals是一个ThreadLocalMap类型的变量,下面我们来看看ThreadLocalMap这个类。在此之前,我们回忆一下Java中的四种引用类型,相关GC只是参考前面系列的文章(JVM相关)

①强引用:Java中默认的引用类型,一个对象如果具有强引用那么只要这种引用还存在就不会被GC。

②软引用:简言之,如果一个对象具有弱引用,在JVM发生OOM之前(即内存充足够使用),是不会GC这个对象的;只有到JVM内存不足的时候才会GC掉这个对象。软引用和一个引用队列联合使用,如果软引用所引用的对象被回收之后,该引用就会加入到与之关联的引用队列中

③弱引用(这里讨论ThreadLocalMap中的Entry类的重点):如果一个对象只具有弱引用,那么这个对象就会被垃圾回收器GC掉(被弱引用所引用的对象只能生存到下一次GC之前,当发生GC时候,无论当前内存是否足够,弱引用所引用的对象都会被回收掉)。弱引用也是和一个引用队列联合使用,如果弱引用的对象被垃圾回收期回收掉,JVM会将这个引用加入到与之关联的引用队列中。若引用的对象可以通过弱引用的get方法得到,当引用的对象呗回收掉之后,再调用get方法就会返回null

④虚引用:虚引用是所有引用中最弱的一种引用,其存在就是为了将关联虚引用的对象在被GC掉之后收到一个通知。(不能通过get方法获得其指向的对象)

分析ThreadLocalMap内部实现

上面我们知道ThreadLocalMap内部实际上是一个Entry数组,我们先看看Entry的这个内部类

当前ThreadLocal的引用k被传递给WeakReference的构造函数,所以ThreadLocalMap中的key为ThreadLocal的弱引用。当一个线程调用ThreadLocal的set方法设置变量的时候,当前线程的ThreadLocalMap就会存放一个记录,这个记录的key值为ThreadLocal的弱引用,value就是通过set设置的值。如果当前线程一直存在且没有调用该ThreadLocal的remove方法,如果这个时候别的地方还有对ThreadLocal的引用,那么当前线程中的ThreadLocalMap中会存在对ThreadLocal变量的引用和value对象的引用,是不会释放的,就会造成内存泄漏。考虑这个ThreadLocal变量没有其他强依赖,如果当前线程还存在,由于线程的ThreadLocalMap里面的key是弱引用,所以当前线程的ThreadLocalMap里面的ThreadLocal变量的弱引用在gc的时候就被回收,但是对应的value还是存在的这就可能造成内存泄漏(因为这个时候ThreadLocalMap会存在key为null但是value不为null的entry项)。

总结:THreadLocalMap中的Entry的key使用的是ThreadLocal对象的弱引用,在没有其他地方对ThreadLoca依赖,ThreadLocalMap中的ThreadLocal对象就会被回收掉,但是对应的不会被回收,这个时候Map中就可能存在key为null但是value不为null的项,这需要实际的时候使用完毕及时调用remove方法避免内存泄漏。

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

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

相关文章

word怎么分页?学会这几招,轻松掌握分页功能!

Microsoft Word作为办公文档处理的主力工具&#xff0c;其强大的排版功能为用户提供了丰富的文档编辑体验。其中&#xff0c;分页是一个常用但可能被忽视的重要功能&#xff0c;能够使文档结构更清晰、更易读。本文将向您介绍word怎么分页的三种方法&#xff0c;帮助您更好地掌…

Linux消息队列 msgget()、msgsend()、msgrcv()、msgctl()

一、消息队列 1、消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2、每个数据块都被认为是有一个类型&#xff0c;接收者进程接收的数据块可以有不同的类型值 3、消息队列与管道不同的是&#xff0c;消息队列是基于消息的&#xff0c;而管道是基于字节流的&…

目标跟踪 MOT数据集和可视化

目录 MOT15数据集格式简介 gt可视化 本人修改的GT可视化代码&#xff1a; MOT15数据集格式简介 以下内容转自&#xff1a;【目标跟踪】MOT数据集GroundTruth可视化-腾讯云开发者社区-腾讯云 MOT15数据集下载&#xff1a;https://pan.baidu.com/s/1foGrBXvsanW8BI4eybqfWg?…

C语言学习第二十六天(算法的时间复杂度和空间复杂度)

1、算法效率 衡量一个算法的好坏&#xff0c;是从时间和空间两个方面来衡量的&#xff0c;换句话说就是从时间复杂度和空间复杂度来衡量的 这里需要补充一点&#xff1a;时间复杂度是衡量一个算法的运行快慢&#xff0c;空间复杂度是主要衡量一个算法运行所需要的额外空间。 …

【操作系统】实验五 文件系统

实验目的&#xff1a; 1. 掌握文件系统的基本概念和工作机制 2. 掌握文件系统的主要数据结构的实现 3、掌握软件系统实现算法 实验内容&#xff1a; 设计并实现一个虚拟的一级&#xff08;单用户&#xff09;文件系统程序 提供以下操作 1、文件创建/删除接口命令 2、目录创建/删…

Java基于微信小程序的小区车位租赁系统的设计与实现

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 简介技术路线需求分析用户信息管理车位信息管理车位申请管理论坛信息管理 效果图推荐阅读 简介 …

【强化学习-读书笔记】动态规划(策略评估、价值迭代、策略迭代算法)

参考 Reinforcement Learning, Second Edition An Introduction By Richard S. Sutton and Andrew G. Barto动态规划 (Dynamic Programming, DP) 是一类优化方法&#xff0c;在给定一个用马尔可夫决策过程 (MDP) 描述的完备环境模型的情况下&#xff0c;其可以计算最优的策…

优化问题笔记(2)

目录 3. 约束优化问题的全局解3.1 凸优化问题3.2 二次优化问题3.3 无约束二次优化问题3.4 一个典型的二次等式约束二次优化问题 Reference 3. 约束优化问题的全局解 3.1 凸优化问题 局部解成为全局解的一类重要的优化问题是所谓凸优化问题. 我们称优化问题 ( f , D ) (f,\ma…

算法-动态规划

动态规划算法 应用场景-背包问题 介绍 动态规划(Dynamic Programming)算法的核心思想是&#xff1a;将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法动态规划算法与分治算法类似&#xff0c;其基本思想也是将待求解问题分解成若干个子问题&#xff0…

Centos7运行pyppeteer报错Browser closed unexpectedly经验总结【必须手动安装谷歌浏览器以自动安装一些依赖】

参考解决方案&#xff1a;pyppeteer.errors.BrowserError: Browser closed unexpectedly - Stack Overflow ldd ~/.local/share/pyppeteer/local-chromium/588429/chrome-linux/chrome | grep not found 注意&#xff1a;安装google-chrome是为了安装这些缺失的so库&#xff0…

针对这两个趋势,3.0全新新零售商业模式可以采取以下策略:

国内市场确实存在“消费升级”和“消费降级”两个趋势&#xff0c;这是由于不同消费者群体的需求和购买力存在差异。消费升级主要发生在高端市场&#xff0c;消费者愿意为高品质、高价值、高价格的商品和服务付出更多。而消费降级则主要发生在中低端市场&#xff0c;消费者更加…

修改antd表单Form.Item的label颜色的方法

默认的Form.item的标签颜色为黑色&#xff0c;但是如果我是用深色背景&#xff0c;这样的情况下表单就看不清楚label了&#xff0c;就像下面的情况&#xff0c;密码两个字完全看不到&#xff0c;所以想把它改为白色字体&#xff0c;就像上面的账号两个字一样&#xff1a; 所以怎…

随笔记录-springboot_LoggingApplicationListener+LogbackLoggingSystem

环境&#xff1a;springboot-2.3.1 加载日志监听器初始化日志框架 SpringApplication#prepareEnvironment SpringApplicationRunListeners#environmentPrepared EventPublishingRunListener#environmentPrepared SimpleApplicationEventMulticaster#multicastEvent(Applicati…

HarmonyOS ArkTS Tab使用方法(十五)

一&#xff0c;使用方法 Android中Java代码使用fragment进行Tab切换&#xff0c;下面使用HarmonyOS ArkTS 语言实现Tab的使用&#xff0c;代码如下&#xff1a; /** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "…

(4)Linux的Redirect 重定向以及打包与压缩

&#x1f4ad; 写在前面 本章仍然是继续对Linux 常用指令进行介绍&#xff0c;将讲解重定向、时间相关的指令、文件查找和打包压缩等指令。我们将初次理解 "Linux下一切皆文件"这一概念&#xff0c;我将通过一个有趣的故事去讲解它。 初识重定向&#xff08;Redire…

如何在本地Docker中部署MinIO服务并实现远程访问管理界面

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

全国巡展“2024人工智能展·世亚智博会”3月上海·4月杭州·6月北京

近年来&#xff0c;我国积极布局人工智能产业&#xff0c;竞跑“未来赛道”。随着各行业、各领域对人工智能需求的日益增长&#xff0c;与实体经济深度融合的新模式不断涌现&#xff0c;形成了具有中国特色的研发体系和应用生态&#xff0c;引领着经济社会各领域从数字化、网络…

web前端项目-影视网站开发

影视网站 本项目主要使用到了 HTML&#xff1b;CSS&#xff1b;JavaScript脚本技术&#xff1b;AJAX无刷新技术&#xff1b;jQuery等技术实现了动态影视网页 运行效果&#xff1a; 一&#xff1a;index.html <!DOCTYPE> <html lang"en"> <head>…

python采集电影数据JS逆向, 并制作可视化

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境使用&#xff1a; Python 3.10 Pycharm nodejs 模块使用&#xff1a; requests -> pip install requests execjs -> pip install pyexecjs json …

电流源输出的是直流电还是交流电(高精度电流源)

电流源是一种能够提供电流输出的电子设备&#xff0c;它可以产生直流电流或交流电流&#xff0c;具体取决于其设计和应用的需要。 首先&#xff0c;我们来讨论电流源输出直流电的情况。直流电是指电流的方向始终保持不变的电流形式。在一些特定的应用中&#xff0c;需要稳定的、…