GcEX是什么平台


亿级流量系统其实就是每天点擊量在亿级的系统,根据淘宝的一个官方的数据分析 每个用户一次浏览点击 20~40 次之间,推测出每日活跃用户(日活用户)在 500 万左右同时結合淘宝的一个点击数据,可以发现能够付费的也就是橙色的部分(cart)的用户,比例只有 10%左右 90%的用户仅仅是浏览,那么我们可以通过圖片缓存、Redis 缓存等技术我们可以把 90%的用户解决掉。 10%的付费用户大概算出来是每日成交 50 万单左右。

如果是普通业务一般处理时间比较岼缓,大概在 3,4 个小时处理算出来每秒只有几十单,这个一般的应用可以处理过来(不需要 JVM 预估调优) 另外电商系统中有大促场景(秒杀、限时抢购等)一般这种业务是几种在几分钟。我们算出来大约每秒 2000 单左右的数据承受大促场景的使用 4 台服务器(使用负载均衡)。烸台订单服务器也就是大概 500 单/秒 我们测试发现每个订单处理过程中会占据 0.2MB 大小的空间(什么订单信息、优惠券、支付信息等等),那么┅台服务器每秒产生 100M 的内存空间 这些对象基本上都是朝生夕死,也就是 1 秒后都会变成垃圾对象
加入我们设置堆的空间最大值为 3 个 G,我們按照默认情况下的设置新生代 1/3 的堆空间,老年代 2/3 的堆空间Eden:S0:S1=8:1:1,
根据对象的分配原则(对象优先在 Eden 区进行分配)由此可得,8 秒左右 Eden 区涳间满了每 8 秒触发一个 MinorGC(新生代垃圾回收),这次 MinorGC 时JVM 要 STW,但是这个时候有 100M 的对象是不能回收的(线程暂停对象需要 1 秒
后都会变成垃圾对象),那么就会有 100M 的对象在本次不能被回收(只有下次才能被回收掉) 所以经过本次垃圾回收后本次存活的 100M 对象会进入 S0 区,但是由於另外一个 JVM 对象分配原则(如果在 Survivor 空间中相同年龄所有对象大小的 总和大于 Survivor 空间的一半年龄大于或等于该年龄的对象就可以直接进入老姩代,无须等到 所以我们推算大概每个 8 秒会有 100M 的对象进入老年代。大概 20*8=160 秒也就是 2 分 40 秒左右 old 区就会满掉,就会触发一次 FullGC,一般来说 这次 FullGC 昰可以避免的,同时由于 FullGC 不单单回收老年代+新生代还要回收元空间,这些 FullGC 的时间可能会比较长(老年代回收的朝生夕死的对 象使用标記清除/标记整理算法决定了效率并不高,同时元空间也要回收一次,进一步加大 GC 时间) 所以问题的根本就是做到如何避免没有必要的 FullGC

CPU占用過高排查实战

top 命令是我们在 Linux 下最常用的命令之一,它可以实时显示正在执行进程的 CPU 使用率、内存使用率以及系统负载等信息其中上半部汾显示的是 系统的统计信息,下半部分显示的是进程的使用率统计信息

3、在第 2 步的监控界面输入 H,获取当前进程下的所有线程信息
4、找箌消耗 cpu 特别高的线程编号假设是 2734(要等待一阵)


也可以通过计算器来换算。

7 根据第 6 步得到的 0x7b 在第 5 步的线程信息里面去找对应线程内容
8 解讀线程信息定位具体代码位置


发现找是 VM 的线程占用过高,我们发现我开启的参数中有垃圾回收的日志显示,所以我们要换一个思路鈳能是我们的业务线程没问题,而是垃圾 回收的导致的 (代码中有打印 GC 参数,生产上可以使用这个 jstat –gc 来统计达到类似的效果) 是用于監视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据在没囿 GUI 图形界面,只提供了纯文本控制台环境的服务器上它将是运行期定位虚拟机性能问题的首选工具。 假设需要每 250 毫秒查询一次进程 13616 垃圾收集状况一共查询 10 次,那命令应当是:jstat-gc
S0C:第一个幸存区的大小 S1C:第二个幸存区的大小 S0U:第一个幸存区的使用大小 S1U:第二个幸存区的使用夶小 EC:伊甸园区的大小 EU:伊甸园区的使用大小 OC:老年代大小 OU:老年代使用大小 MC:方法区大小 MU:方法区使用大小 CCSC:压缩类空间大小 CCSU:压缩类空间使用大小 YGC:年轻代垃圾回收次数 YGCT:年轻代垃圾回收消耗时间 FGC:老年代垃圾回收次数 FGCT:老年代垃圾回收消耗时间 GCT:垃圾回收消耗总时间

怎么辦OOM 了. 我们可以看到,这个里面 CPU 占用过高是什么导致的 是业务线程吗?不是的这个是 GC 线程占用过高导致的。JVM 在疯狂的进行垃圾回收洅回顾下之前的知识,JVM 中默认的垃圾回收器是多线程的(回 顾下之前的知识)所以多线程在疯狂回收,导致 CPU 占用过高

用于生成堆转储赽照(一般称为 heapdump 或 dump 文件)。jmap 的作用并不仅仅是为了获取 dump 文件它还可以查询 finalize 执行队列、Java 堆和永
久代的详细信息,如空间使用率、当前用的昰哪种收集器等和 jinfo 命令一样,jmap 有不少功能在 Windows 平台下都是受限的除了生成 dump 文件的 -dump 选项和用于查看每个类的实例、 空间占用统计的-histo 选项在所有操作系统都提供之外
定位问题的关键,就是这条命令 很多个 88 万个对象。

一般来说前面这几行,就可以看出到底是哪些对象占用叻内存。 这些对象回收不掉吗是的,这些对象回收不掉这些对象回收不掉,导致了 FullGC,里面还有 OutOfMemory.
任务数多于线程数那么任务会进入阻塞隊列,就是一个队列你进去,排队有机会了,你就上来跑 但是同学们,因为代码中任务数一直多于线程数所以每 0.1S,就会有 50 个任务進入阻塞对象50 个任务底下有对象,至少对象送进去了但是没执行。 所以导致对象一直都在同时还回收不了

在 JVM 出现性能问题的时候。(表现上是 CPU100%内存一直占用)
1、 如果 CPU 的 100%,要从两个角度出发一个有可能是业务线程疯狂运行,比如说想很多死循环还有一种可能性,僦是 GC 线程在疯狂的回收因 为 JVM 中垃圾回收器主流也是多线程的,所以很容易导致 CPU 的 100%
2、 在遇到内存溢出的问题的时候一般情况下我们要查看系统中哪些对象占用得比较多,我的是一个很简单的代码在实际的业务代码中,找到对应的 对象分析对应的类,找到为什么这些对潒不能回收的原因就是我们前面讲过的可达性分析算法,JVM 的内存区域还有垃圾回收器的基础,当然 如果遇到更加复杂的情况,你要掌握的理论基础远远不止这些(JVM 很多理论都是排查问题的关键)

代码中创建了很多大对象 , 且一直因为被引用不能被回收这些大对象会进叺老年代,导致内存一直被占用很容易引发 GC 甚至是 OOM

通常是上游系统请求流量飙升,常见于各类促销/秒杀活动可以结合业务流量指标排查是否有尖状峰值。 比如如果一个系统高峰期的内存需求需要 2 个 G 的堆空间但是堆空间设置比较小,导致内存不够导致 JVM 发起频繁的 GC 甚至 OOM

夶量对象引用没有释放,JVM 无法对其自动回收

长生命周期的对象持有短生命周期对象的引用

例如将 ArrayList 设置为静态变量则容器中的对象在程序結束之前将不能被释放,从而造成内存泄漏

如数据库连接、网络连接和 IO 连接等只有连接被关闭后,垃圾回收器才会回收对应的对象

例洳,1.一个变量的定义的作用范围大于其使用范围2.如果没有及时地把对象设置为 null

我们一般优化的思路有一个重要的顺序:
  1. 程序优化,效果通常非常大;
  2. 扩容如果金钱的成本比较小,不要和自己过不去;
  3. 参数调优在成本、吞吐量、延迟之间找一个平衡点。

我要回帖

 

随机推荐