平时如果需要管理项目的话,应该会遇到服务器很卡的场景,最近遇到这块的问题比较多,所以总结了一下这些问题的处理思路及步骤方法。

case 1:检查网络是否正常

访问卡,当然是先ping一下看网速怎样,不能因为网速问题导致傻傻找个半天的程序问题。打开命令行页面,输入 

ping [ip/域名] -t 

查看网络是否正常。

 

case 2:查看控制台日志

服务器卡死了,可以导出tomcat控制台最近的一些日志,比如说导出最近2万行,下载此文件/tmp/out.log到本地或者使用vi查看

tail -n 20000 -v /usr/local/tomcat/logs/catalina.out >> /tmp/out.log

很多情况,服务器崩溃,是发生了一些异常导致的,比如内存溢出以及一些不可预期的异常,可以通过控制台的日志知道异常,然后对症下药,内存溢出,就增大tomcat的jvm内存参数,IO连接数过多,就检查业务代码是否有没正常关闭流或者启用流太多的情况,对其进行优化。

修改jvm内存参数方式:打开/usr/local/tomcat/catalina.sh,在最上面一行增加

JAVA_OPTS="-server -Xms8g -Xmx8g -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m   -Dhttps.protocols=TLSv1.2,TLSv1.1,SSLv3 "

(Xms是创建堆内存初始大小,Xmx是堆内存最大值。两者设置为一致的,那么启动服务会快一些。Xss是每个线程创建的大小,jvm默认是128K,可以设置为1-2M,Xmn为年轻代大小,一般为总堆内存的3/8,具体可以看情况增减。若后台有做较多缓存,比如业务对象缓存,ehcache缓存hibernate相关等,可以减少年轻代大小,jvm会自动调整剩余的为老年代内存空间)

如果没有发现明显异常,那么使用top命令查看服务器当前运行状态,使用ssh工具登录linux服务器,使用

top

命令查看当前各个进程资源占比情况。若mysql等数据库进程资源占比重,则进入case3,若java进程cpu超高,导致服务器卡顿,则看后续case情况处理。

 

case 3:mysql等数据库进程资源占比重

看下数据库是否有死锁或者执行数据量超大超慢的sql,使用ssh工具访问linux服务器,进入mysql后,输入

show processlist

查看当前正在执行的mysql情况。找到异常sql,解决问题。

针对分析mysql日志的情况,可以打开mysql的binlog日志,等待下次发生问题时,去转换并导出binlog日志。

如果没有发现明显异常,继续下一case。

 

case 4:java进程cpu超高线程及JVM堆栈分析

发生此问题就要开始分析堆栈的情况了。

1)导出JVM线程快照

记住上述使用top命令得到的java进程的pid,然后使用

top -p[pid] -H 

命令,可以得到异常的java进程中,哪些线程占用cpu比较大,截个图或者记下这些线程的pid2。

进入linux服务器上的jdk的bin目录(可以使用echo $JAVA_HOME查看jdk安装路径),如果下面的文件没有执行权限,可以输入 chmod +x * ,来增加执行的权限。

cd /usr/java/jdk1.7.0_79/bin/

利用jdk自带的工具导出jvm堆栈快照,

jstack [pid] >> /tmp/heap.log 

其中pid为java进程的id。

打开该日志文件,前面得到的pid2进行10转16进制数,用这个16进制数去日志文件中匹配到对应的线程记录,然后看其正在执行的代码块。

Java平台卡 java运行卡_java堆栈分析

找到对应的问题代码。

如果找到的日志中显示为GC线程,那么就要分析GC的的情况,进入下一步更深的内存分析。

2)导出JVM内存快照

进入linux服务器的jdk的bin目录,输入

jstat -gcutil [pid]  1000 10

指令,获取当前GC的使用情况(这个截图是服务器正常的时候截的图)。

Java平台卡 java运行卡_Java平台卡_02

其中O表示老年代空间占比,这里显示87,表示jvm内存中,老年代已经占了87的内存。而Eden区才占比21,说明年轻代空间充足,而老年代空间已经有点不太够了。

从2个方向分析:

1,jvm参数设置合不合理。年轻代空间太富余,而老年代空间不够。一般按照前面说的,年轻代设置为总堆的3/8,看情况调整。

2,某个区这么高是否正常。一般来说年轻代Eden占比过高,都是可以通过case4-1获取堆栈日志获取当时的堆栈快照,可以知道当时都在执行啥程序,得知是什么问题导致。而一般来说老年代太多,就是有数据一直缓存在后台中,没有释放,可能是需要缓存的数据太多,也有可能是内存泄露。接下来就需要导出具体的内存数据信息了。

jdk自带有工具可以导出内存快照,工具为jmap。dump内存的步骤:

输入命令

jmap -dump:live,format=b,file=/zwj/heap.bin 9568

生成快照文件heap.bin。

Java平台卡 java运行卡_java_03

生成之后,你可以用jhat或者IBM的(heap analyzer)堆栈分析工具打开

 

①jhat是jdk自带的一个用于分析JVM 堆DUMP 文件的工具

jhat -J-Xmx3000m [file名]

执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000

②IBM的heap analyzer是一个jar文件,名为ha456.jar,然后进入命令行页面,进入到此文件所在目录,输入

java -Xmx3000m -jar ha456.jar

就会打开对应的分析工具,然后open file打开前面导出的heap.bin文件。

上述中3000m,是我依据内存文件大小设置的,可依据你内存文件大小来决定设置多少来打开,如果不够的话打开文件时会报内存溢出错误。

还有一些工具可以查看dump出jvm的内存文件,比如eclipse的mat插件。如果内存文件太大,可以用mat插件来分析,也不要直接openfile,而是as reports来查看。

然后就可以去报告分析中去分析内存中到底是啥占用了你的内存。然后看其是否必要以及是否异常,来决定是增大内存还是修改代码还是修复内存泄露bug。