面试常问集锦——线上排查部分

26 篇文章 9 订阅
18 篇文章 12 订阅

实操

线上故障如何快速排查?来看这套技巧大全

https://mp.weixin.qq.com/s/PWNnq07cPYB4o421VFEFHw

JAVA线上故障排查全家桶

https://mp.weixin.qq.com/s/UTGtusIyScJGOjdZPdU4Ug


cpu飚高怎么处理

CPU占用100%排查过程 - 云+社区 - 腾讯云

(1)top 通过top命令找到,找到最耗CPU的进行PID,从下图种可以发现PID为 15913

不断按P可以按照CPU使用率进行排序

(2)top -p 15913 -H ,从下图种可知最耗CPU的两个线程PID分别是 15924和15925,对应的16进制为 0x3e34和0x3e35(进程快照中线程显示是16进制的。)

-H:可以该进程的相关线程信息, -p:指定特定的pid进程号进行观察

printf %x 15924 可以10进制转16进制

(3)jstack 15913 > jstack.log

jstack命令可以得到线程堆栈信息,根据这些线程堆栈信息,可以去检查Java程序出现的问题,如检测死锁。

(4)cat  jstack.log | grep -A 10 0x3e34

-A 10表示,搜索到指定字符串时,在向下打印10行

即可定位到问题代码。


排查GC问题

排查YoungGC问题 

https://mp.weixin.qq.com/s/LRx9tLtx1tficWPvUWUTuQ

线上服务的FGC问题排查

https://mp.weixin.qq.com/s/P8s3kuceBNovUP5adXpFCQ

JVM调优总结 -Xms -Xmx -Xmn -Xss

https://www.cnblogs.com/likehua/p/3369823.html

一次简单的 JVM 调优,性能提升了15%

https://mp.weixin.qq.com/s/rRRZYfjKMyk02pw8y1D99w

一次JVM FullGC的背后,竟隐藏着惊心动魄的线上生产事故!

https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484212&idx=1&sn=94d1c38d84b1d8e5bc8badd73dcd3d24&chksm=fba6eb37ccd16221e6e5bbc72fe71f876213915e1ff5a6bfd666d552ef9baf37104338eabf25&scene=21#wechat_redirect

双12压测引出的线上 Full GC 排查

https://mp.weixin.qq.com/s/G-3d2IhdsEAA-8CG4qZP7g

一次完整的JVM堆外内存泄漏故障排查记录

https://mp.weixin.qq.com/s/dMQatmbM0w1xGPOnhbfh8A

百分百面试题:遇到过线上问题没有?

https://mp.weixin.qq.com/s/H4tqZ1a7YZLymMm30Jwanw


怎么排查oom

怎么排查堆内存溢出啊?

https://mp.weixin.qq.com/s/7XGD-Z3wrThv5HyoK3B8AQ

关于内存安全问题,你应该了解的几点!

https://mp.weixin.qq.com/s/BJUgnDPP2wtUUEjPnCX0oA


怎么实时查看gc信息

jstat查看gc情况_大JAVA解决方案-CSDN博客_jstat查看gc信息

可以在后面加上一个刷新频率,例如jstat -gc 22972 5000代表每5秒输出一次信息

大小的单位为KB

  • S0C:第一个survivor的大小
  • S1C:第二个survivor的大小
  • S0U:第一个survivor的使用大小
  • S1U:第二个survivor的使用大小
  • EC:年轻代的大小
  • EU:年轻代的使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • MC:方法区大小
  • MU:方法区使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • YGC:年轻代垃圾回收次数
  • YGCT:年轻代垃圾回收消耗时间
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

当线上接口请求过慢如何排查?

https://blog.csdn.net/jingyangV587/article/details/103438347

怎么排查接口超时?

https://mp.weixin.qq.com/s/cS69iBMChKabYbvKuBOhQQ


怎么开启慢sql日志

https://juejin.cn/post/6844903876253089806

MySQL索引原理及慢查询优化

https://tech.meituan.com/2014/06/30/mysql-index.html

哪些因素会导致 MySQL 慢查询

https://mp.weixin.qq.com/s/e2Yk2hQUuPBgxxFLiL-Hrw

慢查询引发的车祸现场,案例分析!

https://mp.weixin.qq.com/s/sL64uQP0iHKxkMFx1QGLkg

记一次中间件导致的慢SQL排查过程

https://mp.weixin.qq.com/s/Nt4i6110jfGKFCIPVtydiQ


mysql误删数据快速恢复

https://www.cnblogs.com/-mrl/p/9959365.html


mysql优化

  1. 数据库表设计优化
    1. 所有表必须使用Innodb存储引擎
    2. 字符集统一使用utf-8
    3. 字段加注释
    4. 控制单表数据量的大小,建议控制在500w内
    5. 冷热数据分离,减小表宽度
    6. 禁止存储图片,文件等二进制数据
    7. 三大范式
  2. 数据库字段设计优化
    1. 优先选择符合存储条件最小的数据类型,能用tinyint的就不用int,能用varchar的不用text
    2. 避免使用text,blob数据类型
    3. 尽可能把所有列定义为not null
  3. 索引设计优化
    1. 限制每张表的索引数量,单张表不超过5个
    2. 禁止给每一列都建立单独索引
    3. 每个表必须有一个主键
    4. 频繁查询的字段建立索引
  4. 编写sql优化
    1. 建议预编译语句进行数据库操作
    2. 避免数据类型的隐式转换
    3. 充分利用表上已经存在的索引
    4. 不要使用select * 查询,要使用select <字段列表> 查询
    5. 避免使用子查询,把子查询优化成join操作
    6. 避免使用join关联太多得表
    7. 对同一列进行or判断时,使用in代替or
    8. where从句中禁止对列进行函数转换和计算
    9. 在明显不会有重复值时使用union all而不是union
    10. 拆分复杂的大SQL为多个小SQL
    11. 使用 group by 分组查询是,默认分组后,还会排序,可能会降低速度,在 group by 后面增加 order by null 就可以防止排序.

从实际案例聊聊Java应用的GC优化

https://tech.meituan.com/2017/12/29/jvm-optimize.html


遇到网络问题你是怎么解决的?安琪拉有二招

https://mp.weixin.qq.com/s/z9O62VQn75Rhk5vS42AD-Q


没有监控过JVM内存的职场生涯,是不完美的

https://mp.weixin.qq.com/s/YxO4m0E9K3f6ZTEvC19WeA

常用jdk工具

https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/jvm/JDK%E7%9B%91%E6%8E%A7%E5%92%8C%E6%95%85%E9%9A%9C%E5%A4%84%E7%90%86%E5%B7%A5%E5%85%B7%E6%80%BB%E7%BB%93.md

JDK 命令行工具

这些命令在 JDK 安装目录下的 bin 目录下:

  • jps (JVM Process Status): 类似 UNIX 的 ps 命令。用户查看所有 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息;
  • jstat( JVM Statistics Monitoring Tool): 用于收集 HotSpot 虚拟机各方面的运行数据;
  • jinfo (Configuration Info for Java) : Configuration Info forJava,显示虚拟机配置信息;
  • jmap (Memory Map for Java) :生成堆转储快照;
  • jhat (JVM Heap Dump Browser ) : 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果;
  • jstack (Stack Trace for Java):生成虚拟机当前时刻的线程快照,线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合。

jps:查看所有 Java 进程

jps(JVM Process Status) 命令类似 UNIX 的 ps 命令。

jps:显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一 ID(Local Virtual Machine Identifier,LVMID)。jps -q :只输出进程的本地虚拟机唯一 ID。

C:\Users\SnailClimb>jps
7360 NettyClient2
17396
7972 Launcher
16504 Jps
17340 NettyServer

jps -l:输出主类的全名,如果进程执行的是 Jar 包,输出 Jar 路径。

C:\Users\SnailClimb>jps -l
7360 firstNettyDemo.NettyClient2
17396
7972 org.jetbrains.jps.cmdline.Launcher
16492 sun.tools.jps.Jps
17340 firstNettyDemo.NettyServer

jps -v:输出虚拟机进程启动时 JVM 参数。

jps -m:输出传递给 Java 进程 main() 函数的参数。

jstat: 监视虚拟机各种运行状态信息

jstat(JVM Statistics Monitoring Tool) 使用于监视虚拟机各种运行状态信息的命令行工具。 它可以显示本地或者远程(需要远程主机提供 RMI 支持)虚拟机进程中的类信息、内存、垃圾收集、JIT 编译等运行数据,在没有 GUI,只提供了纯文本控制台环境的服务器上,它将是运行期间定位虚拟机性能问题的首选工具。

jstat 命令使用格式:

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

比如 jstat -gc -h3 31736 1000 10表示分析进程 id 为 31736 的 gc 情况,每隔 1000ms 打印一次记录,打印 10 次停止,每 3 行后打印指标头部。

常见的 option 如下:

  • jstat -class vmid :显示 ClassLoader 的相关信息;
  • jstat -compiler vmid :显示 JIT 编译的相关信息;
  • jstat -gc vmid :显示与 GC 相关的堆信息;
  • jstat -gccapacity vmid :显示各个代的容量及使用情况;
  • jstat -gcnew vmid :显示新生代信息;
  • jstat -gcnewcapcacity vmid :显示新生代大小与使用情况;
  • jstat -gcold vmid :显示老年代和永久代的行为统计,从jdk1.8开始,该选项仅表示老年代,因为永久代被移除了;
  • jstat -gcoldcapacity vmid :显示老年代的大小;
  • jstat -gcpermcapacity vmid :显示永久代大小,从jdk1.8开始,该选项不存在了,因为永久代被移除了;
  • jstat -gcutil vmid :显示垃圾收集信息;

另外,加上 -t参数可以在输出信息上加一个 Timestamp 列,显示程序的运行时间。

jinfo: 实时地查看和调整虚拟机各项参数

jinfo vmid :输出当前 jvm 进程的全部参数和系统属性 (第一部分是系统的属性,第二部分是 JVM 的参数)。

jinfo -flag name vmid :输出对应名称的参数的具体值。比如输出 MaxHeapSize、查看当前 jvm 进程是否开启打印 GC 日志 ( -XX:PrintGCDetails :详细 GC 日志模式,这两个都是默认关闭的)。

C:\Users\SnailClimb>jinfo  -flag MaxHeapSize 17340
-XX:MaxHeapSize=2124414976
C:\Users\SnailClimb>jinfo  -flag PrintGC 17340
-XX:-PrintGC

使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用,请看下面的例子:

jinfo -flag [+|-]name vmid 开启或者关闭对应名称的参数。

C:\Users\SnailClimb>jinfo  -flag  PrintGC 17340
-XX:-PrintGC

C:\Users\SnailClimb>jinfo  -flag  +PrintGC 17340

C:\Users\SnailClimb>jinfo  -flag  PrintGC 17340
-XX:+PrintGC

jmap:生成堆转储快照

jmap(Memory Map for Java)命令用于生成堆转储快照。 如果不使用 jmap 命令,要想获取 Java 堆转储,可以使用 “-XX:+HeapDumpOnOutOfMemoryError” 参数,可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件,Linux 命令下可以通过 kill -3 发送进程退出信号也能拿到 dump 文件。

jmap 的作用并不仅仅是为了获取 dump 文件,它还可以查询 finalizer 执行队列、Java 堆和永久代的详细信息,如空间使用率、当前使用的是哪种收集器等。和jinfo一样,jmap有不少功能在 Windows 平台下也是受限制的。

示例:将指定应用程序的堆快照输出到桌面。后面,可以通过 jhat、Visual VM 等工具分析该堆文件。

C:\Users\SnailClimb>jmap -dump:format=b,file=C:\Users\SnailClimb\Desktop\heap.hprof 17340
Dumping heap to C:\Users\SnailClimb\Desktop\heap.hprof ...
Heap dump file created

jhat: 分析 heapdump 文件

jhat 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果。

C:\Users\SnailClimb>jhat C:\Users\SnailClimb\Desktop\heap.hprof
Reading from C:\Users\SnailClimb\Desktop\heap.hprof...
Dump file created Sat May 04 12:30:31 CST 2019
Snapshot read, resolving...
Resolving 131419 objects...
Chasing references, expect 26 dots..........................
Eliminating duplicate references..........................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

访问 http://localhost:7000/

jstack :生成虚拟机当前时刻的线程快照

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合.

生成线程快照的目的主要是定位线程长时间出现停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者在等待些什么资源。

下面是一个线程死锁的代码。我们下面会通过 jstack 命令进行死锁检查,输出死锁信息,找到发生死锁的线程。

public class DeadLockDemo {
    private static Object resource1 = new Object();//资源 1
    private static Object resource2 = new Object();//资源 2

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource2");
                synchronized (resource2) {
                    System.out.println(Thread.currentThread() + "get resource2");
                }
            }
        }, "线程 1").start();

        new Thread(() -> {
            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource1");
                synchronized (resource1) {
                    System.out.println(Thread.currentThread() + "get resource1");
                }
            }
        }, "线程 2").start();
    }
}

Output

Thread[线程 1,5,main]get resource1
Thread[线程 2,5,main]get resource2
Thread[线程 1,5,main]waiting get resource2
Thread[线程 2,5,main]waiting get resource1

线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通过 Thread.sleep(1000);让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。

通过 jstack 命令分析:

C:\Users\SnailClimb>jps
13792 KotlinCompileDaemon
7360 NettyClient2
17396
7972 Launcher
8932 Launcher
9256 DeadLockDemo
10764 Jps
17340 NettyServer

C:\Users\SnailClimb>jstack 9256

输出的部分内容如下:

Found one Java-level deadlock:
=============================
"线程 2":
  waiting to lock monitor 0x000000000333e668 (object 0x00000000d5efe1c0, a java.lang.Object),
  which is held by "线程 1"
"线程 1":
  waiting to lock monitor 0x000000000333be88 (object 0x00000000d5efe1d0, a java.lang.Object),
  which is held by "线程 2"

Java stack information for the threads listed above:
===================================================
"线程 2":
        at DeadLockDemo.lambda$main$1(DeadLockDemo.java:31)
        - waiting to lock <0x00000000d5efe1c0> (a java.lang.Object)
        - locked <0x00000000d5efe1d0> (a java.lang.Object)
        at DeadLockDemo$$Lambda$2/1078694789.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"线程 1":
        at DeadLockDemo.lambda$main$0(DeadLockDemo.java:16)
        - waiting to lock <0x00000000d5efe1d0> (a java.lang.Object)
        - locked <0x00000000d5efe1c0> (a java.lang.Object)
        at DeadLockDemo$$Lambda$1/1324119927.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

可以看到 jstack 命令已经帮我们找到发生死锁的线程的具体信息。

JDK 可视化分析工具

JConsole:Java 监视与管理控制台

JConsole 是基于 JMX 的可视化监视、管理工具。可以很方便的监视本地及远程服务器的 java 进程的内存使用情况。你可以在控制台输出console命令启动或者在 JDK 目录下的 bin 目录找到jconsole.exe然后双击启动。

连接 Jconsole

如果需要使用 JConsole 连接远程进程,可以在远程 Java 程序启动时加上下面这些参数:

-Djava.rmi.server.hostname=外网访问 ip 地址 
-Dcom.sun.management.jmxremote.port=60001   //监控的端口号
-Dcom.sun.management.jmxremote.authenticate=false   //关闭认证
-Dcom.sun.management.jmxremote.ssl=false

在使用 JConsole 连接时,远程进程地址如下:

外网访问 ip 地址:60001 

查看 Java 程序概况

内存监控

JConsole 可以显示当前内存的详细信息。不仅包括堆内存/非堆内存的整体信息,还可以细化到 eden 区、survivor 区等的使用情况,如下图所示。

点击右边的“执行 GC(G)”按钮可以强制应用程序执行一个 Full GC。

  • 新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
  • 老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。

线程监控

类似我们前面讲的 jstack 命令,不过这个是可视化的。

最下面有一个"检测死锁 (D)"按钮,点击这个按钮可以自动为你找到发生死锁的线程以及它们的详细信息 。

Visual VM:多合一故障处理工具

VisualVM 提供在 Java 虚拟机 (Java Virutal Machine, JVM) 上运行的 Java 应用程序的详细信息。在 VisualVM 的图形用户界面中,您可以方便、快捷地查看多个 Java 应用程序的相关信息。Visual VM 官网:VisualVM: Home 。Visual VM 中文文档:VisualVM: Documentation

下面这段话摘自《深入理解 Java 虚拟机》。

VisualVM(All-in-One Java Troubleshooting Tool)是到目前为止随 JDK 发布的功能最强大的运行监视和故障处理程序,官方在 VisualVM 的软件说明中写上了“All-in-One”的描述字样,预示着他除了运行监视、故障处理外,还提供了很多其他方面的功能,如性能分析(Profiling)。VisualVM 的性能分析功能甚至比起 JProfiler、YourKit 等专业且收费的 Profiling 工具都不会逊色多少,而且 VisualVM 还有一个很大的优点:不需要被监视的程序基于特殊 Agent 运行,因此他对应用程序的实际性能的影响很小,使得他可以直接应用在生产环境中。这个优点是 JProfiler、YourKit 等工具无法与之媲美的。

VisualVM 基于 NetBeans 平台开发,因此他一开始就具备了插件扩展功能的特性,通过插件扩展支持,VisualVM 可以做到:

  • 显示虚拟机进程以及进程的配置、环境信息(jps、jinfo)。
  • 监视应用程序的 CPU、GC、堆、方法区以及线程的信息(jstat、jstack)。
  • dump 以及分析堆转储快照(jmap、jhat)。
  • 方法级的程序运行性能分析,找到被调用最多、运行时间最长的方法。
  • 离线程序快照:收集程序的运行时配置、线程 dump、内存 dump 等信息建立一个快照,可以将快照发送开发者处进行 Bug 反馈。
  • 其他 plugins 的无限的可能性......

这里就不具体介绍 VisualVM 的使用,如果想了解的话可以看:

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SunAlwaysOnline

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值