当前位置:首页 > 科技  > 软件

美团一面,你碰到过CPU 100%的情况吗?你是怎么处理的?

来源: 责编: 时间:2024-05-27 17:15:59 84观看
导读CPU被打满的常见原因1. 死循环在实际工作中,可能每个开发都写过死循环的代码。死循环有两种:在 while、for、forEach 循环中的死循环。无限递归。这两种情况,程序会不停地运行,使用寄存器保存循环次数或者递归深度,一直占

CPU被打满的常见原因

1. 死循环

在实际工作中,可能每个开发都写过死循环的代码。l9p28资讯网——每日最新资讯28at.com

死循环有两种:l9p28资讯网——每日最新资讯28at.com

  1. 在 while、for、forEach 循环中的死循环。
  2. 无限递归。

这两种情况,程序会不停地运行,使用寄存器保存循环次数或者递归深度,一直占用 cpu,导致 cpu 使用率飙升。l9p28资讯网——每日最新资讯28at.com

在使用 JDK1.7 时,还有些死循环比如多线程的环境下,往 HashMap 中 put 数据,可能会导致链表出现死循环。l9p28资讯网——每日最新资讯28at.com

就会导致cpu不断飙高。l9p28资讯网——每日最新资讯28at.com

2.大量GC

我之前参与过餐饮相关的业务系统开发,当时我所在的团队是菜品的下游业务。l9p28资讯网——每日最新资讯28at.com

当时菜品系统有菜品的更新,会发kafka消息,我们系统订阅该topic,就能获取到最近更新的菜品数据。l9p28资讯网——每日最新资讯28at.com

同步菜品数据的功能,上线了一年多的时候,没有出现过什么问题。l9p28资讯网——每日最新资讯28at.com

但在某一天下午,我们收到了大量 CPU100% 的报警邮件。l9p28资讯网——每日最新资讯28at.com

追查原因之后发现,菜品系统出现了 bug,我们每次获取到的都是全量的菜品数据,并非增量的数据。l9p28资讯网——每日最新资讯28at.com

一次性获取的数据太多。l9p28资讯网——每日最新资讯28at.com

菜品修改还是比较频繁的,也就是说我们系统,会频繁地读取和解析大量的数据,导致 CPU 不断飙升。l9p28资讯网——每日最新资讯28at.com

其根本原因是频繁的full gc。l9p28资讯网——每日最新资讯28at.com

3. 大量计算密集型任务

有时候,我们的业务系统需要实时计算数据,比如:电商系统中需要实时计算优惠后的最终价格。l9p28资讯网——每日最新资讯28at.com

或者需要在代码中,从一堆数据中,统计汇总出我们所需要的数据。l9p28资讯网——每日最新资讯28at.com

如果这个实时计算或者实时统计的场景,是一个非常耗时的操作,并且该场景的请求并发量还不小,就可能会导致 cpu 飙高。l9p28资讯网——每日最新资讯28at.com

因为实时计算需要消耗 cpu 资源,如果一直计算,就会一直消耗 cpu 资源。l9p28资讯网——每日最新资讯28at.com

4. 死锁

为了防止并发场景中,多个线程修改公共资源,导致的数据异常问题,很多时候我们会在代码中使用synchronized或者Lock加锁。l9p28资讯网——每日最新资讯28at.com

这样多个线程进入临界方法或者代码段时,需要竞争某个对象或者类的锁,只有抢到相应的锁,才能访问临界资源。其他的线程,则需要等待,拥有锁的线程释放锁,下一次可以继续竞争那把锁。l9p28资讯网——每日最新资讯28at.com

有些业务场景中,某段代码需要线程获取多把锁,才能完成业务逻辑。l9p28资讯网——每日最新资讯28at.com

但由于代码的 bug,或者释放锁的顺序不正确,可能会引起死锁的问题。l9p28资讯网——每日最新资讯28at.com

例如:l9p28资讯网——每日最新资讯28at.com

"pool-4-thread-1" prio=10 tid=0x00007f27bc11a000 nid=0x2ae9 waiting on condition [0x00007f2768ef9000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x0000000090e1d048> (a java.util.concurrent.locks.ReentrantLock$FairSync)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

比如线程 a 拥有锁 c,需要获取锁 d,才能完成业务逻辑。l9p28资讯网——每日最新资讯28at.com

而刚好此时线程 b 拥有锁 d,需要获取锁 c,才能完成业务逻辑。l9p28资讯网——每日最新资讯28at.com

线程 a 等待线程 b 释放锁,而线程 b 等待线程 a 释放锁,两个线程都持有对方需要的锁,无法主动释放,就会出现死锁问题。l9p28资讯网——每日最新资讯28at.com

死锁会导致 CPU 使用率飙升。l9p28资讯网——每日最新资讯28at.com

CPU被打满如何排查

1. 使用系统工具和JDK自带的jstack工具

第一步:使用top命令找出占用CPU最高的Java进程

首先,使用top命令确认是不是Java进程是罪魁祸首。Java进程要么是个后台任务,要么是个jar包,比如一个Spring Boot服务。l9p28资讯网——每日最新资讯28at.com

图片图片l9p28资讯网——每日最新资讯28at.com

假设发现占用CPU 99.7%的线程是Java进程,进程PID为13731。l9p28资讯网——每日最新资讯28at.com

第二步:找到占用CPU最高的线程

接下来,还是用top命令,只不过加一个参数-Hp,就是下面这样:l9p28资讯网——每日最新资讯28at.com

top -Hp 13731

H参数表示要显示线程级别的信息,p则表示指定的pid,也就是进程ID。执行之后,这个Java进程中占用线程占用CPU的情况就列出来了。假设占用CPU最高的那个线程PID为13756。l9p28资讯网——每日最新资讯28at.com

图片图片l9p28资讯网——每日最新资讯28at.com

第三步:保存线程堆栈信息

这就要用到JDK默认提供的一个工具——jstack。jstack用于生成Java进程的线程快照(thread dump)。线程快照是一个关于Java进程中所有线程当前状态的快照,包括每个线程的堆栈信息。通过分析线程快照,可以了解Java进程中各个线程的运行状态、锁信息等。l9p28资讯网——每日最新资讯28at.com

我们用jstack的目的是将那个占用CPU最高的线程的堆栈信息搞下来,然后进一步分析。使用命令jstack pid > out.log将某个进程的堆栈信息输出到out.log文件中。l9p28资讯网——每日最新资讯28at.com

jstack 13731 > thread_stack.log

第四步:在线程栈中查找罪魁祸首的线程

将13756转换为16进制,可以用在线进制转换工具直接转换,比如这个。转换结果为0x35bc。l9p28资讯网——每日最新资讯28at.com

然后在线程栈中,也就是上一步保存的那个thread_stack.log文件,查找这个16进制的线程ID(0x35bc)。l9p28资讯网——每日最新资讯28at.com

这样,我们就能看到需要的线程名称、线程状态,哪个方法的哪一行代码消耗了最多的CPU都很清楚了。l9p28资讯网——每日最新资讯28at.com

图片图片l9p28资讯网——每日最新资讯28at.com

2. 使用Arthas探测工具

Arthas是阿里开源的一款线上监控诊断产品,通过全局视角实时查看应用load、内存、GC、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。l9p28资讯网——每日最新资讯28at.com

安装Arthas

要使用Arthas,你需要先把它安装到你的目标服务器上。l9p28资讯网——每日最新资讯28at.com

  1. 下载jar包:
curl -O https://arthas.aliyun.com/arthas-boot.jar
  1. 启动Arthas服务:
java -jar arthas-boot.jar

启动之后,会列出当前这台服务器上的所有Java进程,选择你要排查的那个服务即可。出现arthas@之后表示已经启动,并成功attach到目标进程上。l9p28资讯网——每日最新资讯28at.com

图片图片l9p28资讯网——每日最新资讯28at.com

可以输入命令dashboard看一下实时面板,默认5秒刷新一次,在这个面板上能够看到线程、内存堆栈、GC和Runtime的基本信息。如果你用过VisualVM的话,操作界面与之类似。l9p28资讯网——每日最新资讯28at.com

找到占用CPU最高的线程

执行thread命令,这个命令会显示所有线程的信息,并且把CPU使用率高的线程排在前面。l9p28资讯网——每日最新资讯28at.com

这样,一眼就看出来了,第一个线程的CPU使用率高达99%。l9p28资讯网——每日最新资讯28at.com

图片图片l9p28资讯网——每日最新资讯28at.com

查看堆栈信息

使用thread ID获取堆栈信息,其实就是jstack pid相同的作用。通过前一步看到这个线程的ID是18,然后执行:l9p28资讯网——每日最新资讯28at.com

thread 18

图片图片l9p28资讯网——每日最新资讯28at.com

直接就看出来了出现问题的位置,比如TestController.java文件的high方法的第23行。然后可以进入代码查看具体问题。l9p28资讯网——每日最新资讯28at.com

参考答案

面试官:“你碰到过CPU 100%的情况吗?你是怎么处理的?”l9p28资讯网——每日最新资讯28at.com

生产环境如果cpu已经被打满了,不要一上来就说什么top,jstack,记住,真实的生产环境如果CPU已经要被打爆了的话l9p28资讯网——每日最新资讯28at.com

第一选择肯定是重启,并且如果你近段时间有发布的话,还要考虑是否可以回滚,保障生产环境的稳定性是最重要的l9p28资讯网——每日最新资讯28at.com

还有就是,如果CPU已经被打爆了,不管arthas还是jstack大概率也是执行不了的,jvm无法响应l9p28资讯网——每日最新资讯28at.com

我:“之前碰到过CPU被打满的情况,我们线上第一时间做了重启,在重启的过程中,我们去查了服务在那段时间的日志、链路、指标,没有发现特殊的异常。”l9p28资讯网——每日最新资讯28at.com

有时候CPU100&会伴随非常明显的日志、链路或者指标异常。例如:通过gc的指标发现,发现full gc的次数激增,或者发现内存的使用率很高,这个时候大概率是因为gc导致的cpu 100%。这个时候就不要再去jstack了,应该第一次时间查看堆dump文件,确认是哪个对象占用了大量内存l9p28资讯网——每日最新资讯28at.com

我:“当服务重启完成后,我们开始排查具体的原因。我们通过定期执行top命令,发现java进程的CPU的使用率确实在慢慢增加”l9p28资讯网——每日最新资讯28at.com

我:“接着,我通过top -Hp以及jstack命令拿到了应用里cpu使用率最高的那个线程的堆栈,通过分析堆栈最终定位到了具体的代码,是因为代码触发了一个临界值,进入了死循环”l9p28资讯网——每日最新资讯28at.com

下面这段代码是我实际工作碰到一个导致线上CPU 100%的代码:l9p28资讯网——每日最新资讯28at.com

public ShortUrlRandomSeed getAvailableSeed()  {  MachineInfo machineInfo = UrlConverUtil.getMachineInfo();  for (; ; ) {    // 获取种子    ShortUrlRandomSeed seed = shortUrlSeedService.getAvailableSeed(machineInfo);    if (seed != null) {      int influenceNum = shortUrlSeedService.updateSeedStatus(seed.getId());      if (influenceNum > 0) {        return seed;      }    }  }}

这段代码的作用是为了获取一个种子用于短链的生成,在项目上线之初预生成了接近21w个种子,这个代码在线上跑了3年了一直没有问题,直到去年的某一天,21w个种子用光了,seed一直为null,开始死循环,最终导致CPU 100%l9p28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-91012-0.html美团一面,你碰到过CPU 100%的情况吗?你是怎么处理的?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 机械师 10 周年:科技致敬时光,旗舰 mini GTX 上市热销

下一篇: 分布式一致性必备:一文读懂Raft算法

标签:
  • 热门焦点
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 线程通讯的三种方法!通俗易懂

    线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • Flowable工作流引擎的科普与实践

    Flowable工作流引擎的科普与实践

    一.引言当我们在日常工作和业务中需要进行各种审批流程时,可能会面临一系列技术和业务上的挑战。手动处理这些审批流程可能会导致开发成本的增加以及业务复杂度的上升。在这
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • ESG的面子与里子

    ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 微博大门常打开,迎接海外画师漂洋东渡

    微博大门常打开,迎接海外画师漂洋东渡

    作者:互联网那些事&ldquo;起猛了,我能看得懂日语了&rdquo;。&ldquo;为什么日本人说话我能听懂?&rdquo;&ldquo;中文不像中文,日语不像日语,但是我竟然看懂了&rdquo;&hellip;&hell
  • 三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    7月29日消息,三星率先发力可折叠手机市场,在全球市场已经取得了非常亮眼的成绩,接下来会进一步巩固和扩大这一优势。三星在推出Galaxy Z Flip5和Galax
  • iQOO Neo8 Pro真机谍照曝光:天玑9200+和V1+旗舰双芯加持

    iQOO Neo8 Pro真机谍照曝光:天玑9200+和V1+旗舰双芯加持

    去年10月,iQOO推出了iQOO Neo7系列机型,不仅搭载了天玑9000+,而且是同价位唯一一款天玑9000+直屏旗舰,一经上市便受到了用户的广泛关注。在时隔半年后,
  • 英特尔Xe HPG游戏显卡:拥有512EU,单风扇版本

    英特尔Xe HPG游戏显卡:拥有512EU,单风扇版本

    据10 月 30 日外媒 TheVerge 消息报道,英特尔 Xe HPG Arc Alchemist 的正面实被曝光,不仅拥有 512 EU 版显卡,还拥有 128EU 的单风扇版本。另外,这款显卡 PCB
Top
Baidu
map