您的位置:首页 > 编程语言 > Java开发

性能监控与性能问题定位之:Java篇

2012-06-12 11:37 190 查看
阅读本文之前建立对Java(JVM、GC)和其Web服务程序有所了解。
以下是Java自带的性能监控工具

jps(jps -mlvV)与Linux上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。
jstat(man jstat | jstat -gc $jpid)监视VM内存工具,可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。
jmap(Memory Map |jmap -heap $jpid)打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。
jstack(Linux特有| jstack -l $jpid)观察jvm中当前所有线程的运行情况和线程当前状态。
jinfo(Linux特有| jinfo $jpid)运行中的java程序的运行环境参数,参数包括Java System属性和JVM命令行参数
jconsole结合上述功能的GUI工具,监控到:CPU、内存、线程数、类数量,展现VM摘要、Mbean集属性。
jvisualvmJava5之后内置的监控工具,和Jconsole相似,Dump功能强大!并有Profile功能。
jhat用于解析Java的Dump文件,并启动Web服务供浏览。
必要时我们需要抓取Java全内存的Dump来分析,抓取方式有如下:

jmap -dump <options>
jvm中添加参数:-XX:+HeapDumpOnOutOfMemoryError 在符合条件时会输出Dump。
hprof输出:java -agentlib:hprof[=options] ToBeProfiledClass | java -agentlib:hprof=help
jvisualvm:有界面,可生成各种镜像和Dump。
那么Dump怎样分析呢?

jhat用于解析Java的Dump文件,并启动Web服务供浏览。
mat(Memory Analyzer)开源分析工具,可形成报告。官网:http://www.eclipse.org/mat/
JDK还内置了一些演示程序供参考,给被监控程序添加启动参数后执行以下指令:

java -jar $JAVA_HOME/demo/management/MemoryMonitor/MemoryMonitor.jar
192.168.223.108:8950
java -jar $JAVA_HOME/demo/management/FullThreadDump/FullThreadDump.jar 192.168.223.108:8950
java -jar $JAVA_HOME/demo/management/JTop/JTop.jar 192.168.223.108:8950
java -jar $JAVA_HOME/demo/management/VerboseGC/VerboseGC.jar 192.168.223.108:8950
OK,由于篇幅限制,接下来介绍一下商业监控工具吧:

Jprofilerhttp://www.ej-technologies.com/
JRockithttp://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
Yourkithttp://www.yourkit.com
Jprofiler专门针对Java性能监控设计。

JRockit则是一套JVM,有其配套的监控系统和工具。

Yourkit没用过,出品了java和.net的监控。

废话不多说,下面我来演示一下如何Jprofile来定位Java的性能问题。以Jboss为例:

在/usr/local/jboss/bin/run.conf里添加JAVA_OPTS:`-agentpath:libjprofilerti.so=port=8849`,启动Jboss。

这里我做了示例程序,在此理解为某产品的三个版本。访问方式如下:
http://TestServer/Servlet/Demo?Version=1 http://TestServer/Servlet/Demo?Version=2 http://TestServer/Servlet/Demo?Version=3
性能体现如下:

v1:正常,性能好且表现稳定(点击率曲线平稳在6600)

v2:性能下降明显(点击率曲线平稳在2800),需要尽快找出原因

v3:程序不稳定,运行越来越慢(刚启动是点击率约4200,随后渐跌至0),久了就宕机(后台抛内存溢出)

使用Jprofile监控,问题轻松被定位。如下图:

1、“CPU Views”部分为进行v2的测试过程截图。问题定位在加解密上,即这块需要优化。

2、“Heap Walker”部分为进行v3的测试过程截图。问题定位在Session处理上,说明Session机制需要调整。



上述示例的代码也贴出来了,AES加密代码较多未贴需要读者自己实现了:


package com.higkoo.tester;

public class
Demo extends
HttpServlet {

public void
doGet(HttpServletRequest
request,
HttpServletResponse response)

String version
= request.getParameter("Version");

response.setContentType("text/html ;charset=UTF-8");

response.setHeader("Cache-Control", "no-cache");

PrintWriter
out = response.getWriter();

String result
= new
String();

String rand
= UUID.randomUUID().toString();

if(version==null)
version = "0";

switch(Integer.parseInt(version)){

case 1:

result
= "Version1:" +
ClacMD5(rand);

break;

case 2:

result
= "Version2:" +
ClacAES(rand);

break;

case 3:

result
= "Version3:" +
MakeSession(request,rand);

break;

default:

result
= "Default:" + "Hello higkoo !";

break;

}

out.write(result);

out.close();

}

public String
ClacMD5(String
str){

MessageDigest
md = MessageDigest.getInstance("MD5");

byte[]
array =
md.digest(str.getBytes("utf-8"));

StringBuffer sb
=new StringBuffer();

String result
= new
String();

if(str
!=null){

for(int
i =0;
i <
array.length;
i++){

sb.append(Integer.toHexString((array[i]&0xFF)|0x100).toUpperCase().substring(1,3));

}

result
= sb.toString();

}

return result;

}

public String
ClacAES(String
str){

String kStr
= "866563b712d204d82876d1153d06c1f11";

String result
= new
String();

String eStr
= AESUtil.encrypt(AESUtil.encrypt(AESUtil.encrypt(str.replaceAll("-",
""), kStr),kStr),kStr);

result =
AESUtil.decrypt(AESUtil.decrypt(AESUtil.decrypt(eStr,
kStr),kStr),kStr);

return result.toUpperCase();

}

public String
MakeSession(HttpServletRequest
request,String
str) {

HttpSession
session=request.getSession(true);

session.setAttribute("accessCount",
str);

return session.getId() ;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: