java问题定位思路总结(转)

很久没写文章了,java相关问题定位方法很久之前就在酝酿,一直没时间下笔,有时候需要按项目的方式逼着自己做些事情。前段时间看到一些相关文章,自己也尝试做下相关总结,如有错误还望大家多多指正。

快速准确的定位出在线问题,需要不断地学习总结,抽丝剥茧,剖析出问题本质。定位一个问题的过程,就像是医生诊治的过程一样,需要通过望闻问切、听诊、医疗器械等方式探查病情,并根据人的生理机制,分析问题原因,对症下药。定位进程问题与之有异曲同工之处,只不过诊治过程是与人沟通,定位进程问题是与机器、进程、代码逻辑沟通。

与人交谈,需要大家都理解的语言,同理,与机器、进程交谈(即定位问题)也需要大家都能理解的语言,即命令和工具。机器不会主动说话但会被动回答,定位问题的过程,需要我们主动问机器,机器会根据我们的提问,返回他当前的感受。因此,我们需要熟知一些基本的工具及返回结果的含义。

工欲善其事必先利其器,首先我们需要了解相关基础原理及工具使用,原理包括机器层面、linux相关原理、jvm相关原理、服务相关原理等,工具包括linux各种命令、jvm jdk相关命令、各个服务metric指标和操作工具等。下面将由下到上(机器->操作系统->jvm->服务)从4个方面介绍,但是实际定位问题时的路径是由上到下(服务->jvm->操作系统->机器)。
机器架构

现今大部分计算机都基本遵循冯·诺伊曼结构,基本包括cpu、内存、磁盘、网卡(此文对显卡/交换机/路由器等其他设备不做讨论)。

cpu:负责运行机器指令,是机器的核心,cpu相关的问题也是生产中经常遇到的问题,按指令集分为CISC和RISC,按多核组织方式分为SMP/MPP/NUMA,当前大多数服务器使用NUMA架构。
内存:包含L1/L2/L3 cache、主存、虚拟内存等,缓存主要解决cpu速度和内存读写速度差距较大问题,由于缓存是顺序预读机制,在编写程序时注意顺序处理数据,可提高缓存命中率,程序性能得到很大提升。
磁盘:按磁盘类型分为HDD/SSD/HHD/M.2等,按接口协议分为sata、sas、scsi、nvme等。不同接口和不同磁盘类型影响磁盘的整体性能。传统hdd硬盘,涉及到扇区、磁道寻址等,顺序读写和随机读写性能差距很大,可能达到几百倍,一般情况下,单裸盘,顺序读写可以达到200MB/s左右,随机读写可以达到60MB/s左右。ssd从存储机制层面解决了hdd的问题,顺序和随机读写性能差距不大,不同的接口和ssd类型读写性能差距较大,如nvme比sata性能高至少2倍以上。
网卡:按速度分为1000Mbps千兆、10Gbps万兆、40Gbps、100Gbps。机器可以选择双网卡做bond以达到负载均衡及容灾效果。

linux相关

从硬件层面了解了相关组件,下面最重要的就是要了解操作系统的原理,应用程序与硬件直接是通过操作系统进行关联、交互的。现在大部分服务器都是基于linux的,因此,熟悉linux的基本原理和基本命令使用,是定位问题的关键所在。linux内核是个非常复杂的系统,对大多数人,只需要掌握基本概念以及相关工具的使用即可。
cpu相关

分析cpu常用的工具有top、ps、sar、mpstat、dstat、pidstat、perf、strace、proc等,简单介绍两个常用的。
top

top命令是查看cpu的基本命令,可以得到的信息有:

系统启动时长:up xxx,查看系统启动时间还可用who -b/last reboot等命令
最近1/5/15分钟平均负载:load average xxx,表示正在运行和等待运行的进程数,注意cpu利用率高和磁盘利用率高都可能导致负载上升,需注意这两种情况。通过3个值也可以看出当前机器是逐渐变空闲还是变繁忙
进程数:Tasks: xxx,总数、running数、sleeping数、stopped数、zombie数
cpu利用率:%Cpu(s) xxxx
    us/sys/ni表示用户空间、内核空间、用户空间内改变优先级占用cpu百分比
    id:空闲态cpu占比,此值较高表示cpu较空闲
    wa:等待输入输出cpu占比,此值过高一般表示磁盘压力过大
    hi/si/st:硬中断、软中断、偷走时间(如虚拟机等)
内存情况、swap情况
进程详细情况:虚拟内存使用、实际内存使用、共享内存使用等

top可以定位到某个进程是否有问题,top -Hp $pid可查看指定进程的所有线程情况,基本定位到是某个线程的问题,然后根据线程ID,使用jstack命令查看java进程相关线程的情况即可(注意jstack的输出为16进制线程号,需做转换)。
ps

可查看进程的状态

ps axu | grep xxx:可查看进程的pid、启动用户、内存占用情况、进程状态、启动命令等���息
    进程状态有:D/R/S/T/W/X/Z/</N/L/s/l/+,如果出现大量的D、Z状态进程则需额外注意,进程一般情况下处于S/R/l状态
ps -ef | grep xxx:可查看进程的pid和父进程id
ps -eLf | grep xxx:可查看所有轻量级进程(LWP)情况

proc文件系统

proc文件系统中,存放内核中运行状态的各种信息,了解这个文件内含义,非常重要,如机器cpuinfo、meminfo、vmstat、diskstats、net、进程的env/stat/fd等各种详细信息,基本上大部分工具的结果都是从proc中获取相关信息进行汇总后的展示。

关于cpu,生产中也踩过不少坑,如机器温度高被降频、cpu performance模式未开启、cpu中断affinity设置等问题。
内存相关

内存分析,常用的工具有free、top、vmstat、pmap、ps、slabtop、cachestat、/proc/meminfo、/proc/vmstat等

free:查看当前内存、swap、buff/cache等使用情况
vmstat:-a/-s显示更加详细信息,如active/inactive mem、swap等信息,其中inactive涉及到LRU页面回收算法,当inactive过多,说明页面较慢,可能磁盘有问题(详情可了解INACTIVE_ANON与INACTIVE_FILE)
top:可按进程的mem进行排序,找到占用内存较高的进程,进行分析处理,这里需注意VIRT/RES/SHR三者区别
cachestat:可查看pagecache使用及命中率情况

磁盘相关

通常情况下,磁盘是最慢的物理设备,因此针对磁盘问题的定位和调优,是需要着重考虑的。关于磁盘的常用命令有:iostat、iotop、df、du、fdisk、blktrace、cachestat等。

磁盘的常用调度策略有:noop/deadline/cfq,可在/sys/block/xxx/queue/scheduler中动态调整,新内核默认开启scsi_mod.use_blk_mq,新的磁盘调度策略为bfq/kyber/mq-deadline/none。

磁盘的文件系统有xfs、ext4等,还可做阵列,以提高可用性、性能等,如raid0、raid1、raid5、raid10等。

iostat:-dx sdx 1,查看磁盘性能指标,包括读写merge情况、读写次数、读写速率、读写队列、读写wait、磁盘服务时间svctm、磁盘使用率util
iotop:可以查看磁盘总读写速率、每个进程/线程的读写情况,按左右键可指定排序列,找到对应的进程或线程,分析相关问题
df:查看磁盘使用情况,-T查看磁盘类型,-i查看inode使用
blktrace:当遇到磁盘问题时,用blktrace分析io过程中那个过程最耗费资源,如请求排队、排序、写盘等过程
fdisk:列出磁盘信息,分区操作等

网络相关命令

网络问题的分析是最难的,涉及的面非常广,如cpu调度、affinity设置、内存配置、队列配置、网卡配置、交换机配置、tcp协议配置等等。

网络常用的命令有:ifconfig、ethtool、netstat、ss、tcpdump、iftop、ping、traceroute、dig、wget、scp、ssh等。网卡有接收队列和发送队列,涉及到ringbuffer。tcp有半连接队列和全连接队列,涉及到server端握手过程。如果遇到drop、overflow、ofoprune等情况,则需要考虑ringbuffer、tcp_max_syn_backlog/somaxconn、rmem_max等值是否合理,另外需要查看对应内存的使用情况。

ifconfig:查看网卡基本信息,如ip地址、mac地址、接收/发送包情况(error、drop、overrun等)
ethtool:查看网卡基本信息,如网卡速度,-g/-G可查看/调整ring buffer大小
netstat:-s可以看各网络协议包发送情况,tcp/udp等。当连接数很多时,查看每个连接的信息会非常慢,需使用ss
ss:-anp,查看每个连接的状态、接收/发送队列、ip端口等信息,还可查看全连接队列的大小(默认50)
iftop:查看网络使用排行榜和总体网络使用速率,-P可显示本机和对端端口,
tcpdump:抓包工具

其他常用命令

grep、tail、xargs、awk、cat、find、less、sort、uniq、tr、comm、for、while等常用命令的灵活使用,可帮助分析和处理日志文件,如切分、统计个数、排序、交集等,帮助发现各种隐藏问题。
jvm相关原理

定位jvm相关问题,需要深入学习java内存模型、垃圾回收、相关工具使用。
java内存模型

学习堆、栈、堆外、元空间、happens-before原则、java异常体系等概念。

堆:java对象分配空间,垃圾回收重点区域,此空间可能会抛出OutOfMemoryError。分为Eden/Survivor/Old三个区
栈:本地方法栈/虚拟机栈、局部变量表、引用、方法返回地址等,此空间可能会抛出StackOverflowError/OutOfMemoryError
堆外
元空间:每个加载器分配专门的空间
java异常体系(基类Throwable)
    Error:非检查异常,程序无法处理,如OutOfMemoryError、StackOverflowError、NoClassDefFoundError、NoSuchMethodException等
    Exception:程序可处理
        RuntimeException(非检查异常):NullPointerException、NumberFormatException、ArrayIndexOutOfBoundsException、ArithmeticException、ClassCastException等
        非运行时异常(检查异常)

垃圾回收

学习young/old区、STW、SafePoint、SafeRegion、串行/并行/并发、复制、标记清除、标记整理、8种垃圾回收器等概念。

young区:2个eden+1个survivor,使用复制算法,所有young的gc都是stw的
old区:使用标记清除或标记整理算法
STW:stop-the-world,严重影响程序性能,尽量减少发生频次
SafePoint/SafeRegion:所有线程进入安全检查点,才能进行gc
串行/并行/并发:垃圾回收器有串行、并行和并发,串行和并行会产生STW,并发不会
8种垃圾回收器
    young区:Serial、ParNew、ParallelScavenge
    old区:CMS、Serial-Old、Parallel-Old
    both:G1、ZGC
    当前主流的还是cms、g1,ZGC是方向

相关工具

熟悉常用工具:jstack、jmap、jstat、jinfo、mat、arthas、nmt、perf、strace、gdb等

jstack:打印线程栈

jmap:dum内存、-histo:live会触发fgc

jstat:动态打印内存各个区域使用情况

jinfo:查看jvm相关参数,可动态设置一些jvm参数

mat:分析jmap dump下的内存

arthas:阿里开源的强大分析工具

nmt:定位jvm直接内存使用情况(通过本地方法使用的内存无法追踪)

strace:跟踪系统调用情况

gdb:dump内存gdb --batch --pid 11 -ex "dump memory a.dump 0x7fd488000000 0x7fd488000000+56124000",然后使用strings a.dump | less或者hexdump -C a.dump | less或者view a.dump查看。用于分析堆外内存

perf:perf record、perf report

基本问题定位

cpu问题(cpu使用率过高、死锁、卡住等情况)
    top找到对应的进程,top -Hp找到对应的线程,jstack找到对应的线程栈(注意16进制转换)
    arthas、strace、perf进行性能分析

堆内内存问题:jstat查看内存使用情况及gc情况,jmap -histo:live/jmap dump结合mat分析内存使用情况

堆外内存问题:nmt跟进,gdb dump

服务原理

掌握上述基本原理及工具,还需要掌握服务的原理,构建完善的监控指标,才能有的放矢,知道问题出错的地方并做相关验证工作。
hive

整体过程为:sql -> ast -> 逻辑执行计划 -> 物理执行计划 -> 执行 -> 返回。

sql -> ast:使用antlr编译,需满足语法规范
ast -> 逻辑执行计划:解析table/join/gby/union/udf等,并做优化,如条件下推、分区剪枝、列剪枝、distinct转换、mapjoin、join顺序调整等
逻辑执行计划 -> 物理执行计划:按ReduceSinkOp切分为多个MapRedTask、MoveTask等,并做优化,如小文件合并、task合并等
执行:按task的dag图执行mr,需注意map/reduce/am相关问题(预聚合、数据倾斜问题)

spark(on yarn)

主要有3个组件服务:driver、am、executor。

driver:负责资源管控、dag切分、stage依赖调度、task分发、executor管理,是高频出现问题的组件
am:spark支持client/cluster模式,am负责与yarn交互,主要负责资源的申请和释放
executor:负责task执行、数据读写与存储(broadcast/persist/cache)、注册并读写shuffle数据,需注意gc问题、task分发问题
job/stage/task分析,需注意数据倾斜问题、task分发均衡问题等

yarn

主要有三个组件:RM(主从)、NM、ZK。

RM:负责总体资源的管控和协调,如nm的注册及心跳信息处理、队列资源的管理和分配、application的管理,重要指标有rpc处理时间、各个队列调度指标、container分配时间、gc情况等
NM:负责管理当前机器资源、拉起释放和监控container、日志聚合等
ZK:记录app状态信息,保证宕机恢复;用于选主

hdfs

主要有五个组件:zkfc、nn、jn、dn、zk。

zkfc:自动选主
nn:主节点,分为active/standby,管理所有存储资源、目录树、文件信息、block信息、权限信息等;接收并处理元信息请求,如mkdir、rm等;lease管理等。重要指标有rpc处理时间、排队时间、元信息情况、gc情况等
jn:journal node,负责edit log读写,保证active/standby节点数据保证一致,保证高可用
dn:负责管理当前节点的存储资源、block信息、数据存储与转发等。重要指标有rpc处理时间、读写数据情况、磁盘io情况、读写block情况、block report情况、gc情况等
zk:选主

kafka

主要有三个组件:controller、broker、zk。

controller:负责元信息管理,topic的创建、删除、扩partition、reassgin等
broker:管理当前节点资源,partition数据读写、主从同步、leader和follower管理、consumerGroupCoordinator、offset管理
zk:存放topic、partition、权限等元数据,controller选主等

主要指标有ur个数、partition主从个数、isr情况、network/request idle指标、request/response queue size、active controller个数、producer/consumer读写情况、lag情况、cache情况、jvm情况等

作者:外星人roncen
链接:https://www.jianshu.com/p/c54c96b1fb5a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


Share Tweet Send
0 Comments
Loading...
You've successfully subscribed to 隔窗听雨
Great! Next, complete checkout for full access to 隔窗听雨
Welcome back! You've successfully signed in
Success! Your account is fully activated, you now have access to all content.
豫ICP备19045256号-1