Let's Go!

自己动手创建 AIX 平台上的性能监测工具(转载)

上一篇 / 下一篇  2011-08-30 14:22:00 / 个人分类:测试工具

http://www.ibm.com/developerworks/cn/aix/library/0810_daijw_monitor/index.html

 

简介: 对于 AIX 平台上的系统测试人员来说 , 经常需要监测系统和应用程序的 CPU 和内存使用情况。操作系统自带的性能工具由于不具有数据分析和图形化的报表功能 , 使用起来非常不方便。本文介绍了如何利用 AIX 操作系统自带的性能工具以及 JFreeChart 图库去轻松构建一个适于自己项目需要的性能监测工具。

 

简介

AIX 操作系统提供了很多性能相关的工具包,比如 perfagent.tools,bos.acct,bos.sysmgt.trace, bos.adt.samples,bos.perf.tools 以及 bos.perf.tune。它们提供了很多可以对系统性能进行监测和调优的工具。比如,监测网络活动的 netpmon,监测内存使用情况的 svmon,监测文件系统性能的 filemon,设置网络属性的 no。

JFreeChart 是一个开源的 Java lib 库,利用 JFreeChart 可以用来生成各种各样的图表,比如饼图、柱状图、线图、区域图、分布图、混合图、甘特图。

我们要创建的监测工具如下图 1 所示,可以分成两部分,一部分位于被监测的 AIX 机器 , 用来监测系统性能数据;另外一部分位于另一台机器,用来根据性能数据生成基于 WEB 的性能图表。虽然这两部分也可运行于同一台机器,但是为降低对被监测系统的性能影响,推荐将绘制图表的工作放到另一台机器上执行。


图 1 性能监测工具示意图

下面,我就介绍如何利用 AIX 的性能工具包和 JFreeChart 来创建一个简单易用的性能监测工具。


开始之前

在开始创建性能监测工具之前,请做下列准备:

  • 准备两台机器,一台是被监测的 AIX 机器 , 另外一台机器用于生成图表 ( 在文中,我们用一台 Linux 机器为例 )。
  • 由于我们在采集内存和 CPU 数据时需要用到 bos.perf.tools 和 bos.acct 工具包中的命令,在使用这些命令之前,请执行下面的命令来确保 bos.perf.tools 和 bos.acct 工具包已经被正确安装在你的 AIX 机器上。

# lslpp -lI bos.perf.tools bos.acct

如果工具包已经正确安装,会有下面类似的输出:

Fileset Level State Description 
 ----------------------------------------------------------------------------
 Path: /usr/lib/objrepos
 bos.acct 5.3.0.30 COMMITTED Accounting Services 
 bos.perf.tools 5.3.0.30 COMMITTED Base Performance Tools 

 Path: /etc/objrepos
 bos.acct 5.3.0.30 COMMITTED Accounting Services 
bos.perf.tools 5.3.0.30 COMMITTED Base Performance Tools

  • 通过下面的 URL 下载最新的 JFreeChart lib 到 Linux 机器上

http://www.jfree.org/jfreechart/download.html

http://sourceforge.net/project/showfiles.php?group_id=15494

  • 由于 JFreeChart 需要 JDK1.3 或者更高版本的支持,请下载并安装 JDK 到 Linux 机器上
  • 在 Linux 机器上搭建一个 WEB 服务器,这样我们就可以把生成的性能数据和图表发布到 WEB 上。
  • 通过下面的 URL 下载最新的 STAF 并且安装到 AIX 和 Linux 机器上。

http://staf.sourceforge.net/getcurrent.php

为了能通过 STAF 传送数据文件,这两台机器还必须互相赋予一定的权限。因此在安装 STAF 之后,启动 STAF 之前,我们需要按照下面的方法分别修改 STAF 的配置文件。

在 Linux 机器 ( 假定 IP 地址为 9.168.0.2) 的 STAF 配置文件 /usr/local/staf/bin/STAF.cfg 里添加如下内容:

TRUST LEVEL 5 MACHINE tcp://9.168.0.1

在 AIX 机器 ( 假定 IP 地址为 9.168.0.1) 的 STAF 配置文件 /usr/local/staf/bin/STAF.cfg 里添加如下内容:

TRUST LEVEL 5 MACHINE tcp://9.168.0.2


监测性能数据

为方便说明起见,我们假定需要监测下列性能数据:

  • 系统的内存使用情况
  • 系统的 CPU 使用情况
  • 某个特定进程的内存使用情况 ( 比如 java)


对于系统的内存使用情况,我们可以用 svmon 命令的 -G 选项来收集数据。需要注意的是,svmon 输出的内存大小以 pages 为单位,1 page 等于 4kBytes。Svmon –G 的命令输出如下:

bash-3.00# svmon -G
 size inuse free pin virtual
memory 2031616 512534 1519082 145239 295968
pg space 2097152 1214

 work pers clnt
pin 145239 0 0
in use 295968 0 216566

对于系统的 CPU 使用情况,我们可以用 sar 命令的 -u 选项来收集数据。需要注意的是,-u 选项收集的是 system-wide 的 cpu 数据,如果是多 cpu 系统,命令输出的则是多个 cpu 的使用情况。如果需要某个特定 cpu 的使用情况,则需要用 -P 选项指定 CPU。Sar –u 的命令输出如下,”1”表明只采集一个时间点。

bash-3.00# sar -u 1

AIX test19 3 5 00034ADAD300 07/23/08

System configuration: lcpu=4 

14:41:54 %usr %sys %wio %idle physc
14:41:55 0 0 0 100 2.00

对于特定进程的内存使用情况,我们可以用 svmon 命令的 -P 选项来收集数据。-P 选项后面要跟进程 id,所以在运行 svmon –P 之前我们必须先取得要监测的进程 id。svmon –P 的命令输出如下 :

bash-3.00# svmon -P 1450024

---------------------------------------------------------------------
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB
1450024 java 99308 7384 0 79641 N Y N

知道如何用命令监测我们需要的性能数据后,就可以开始动手编写脚本 aixperfmonitor.sh 来分析命令的输出,把需要的数据写到相应的数据文件当中去以便于后面绘制性能图表。另外,这个脚本也包含按照设定的时间间隔持续监测性能数据的功能。


清单 1 aixperfmonitor.sh

#!/bin/sh

function usage {
 echo "Usage aixperfmonitor.sh -t <duration> -i <interval>"
 echo " where:"
 echo " -t: total monitor duration in minutes"
 echo " -i: monitor interval in minutes"
 echo ""
 exit
}

function checkProcess {
 
 # 如果有多个以 java 命名的进程,还需通过别的关键字精确选取要监测的 java 进程
 ret=`ps -ef|grep java|grep WebSphere`
 if [ $? -ne 0 ]; then
 JAVARun=0
 else
 javapid=`ps -ef|grep java|grep WebSphere|awk '{print $2}'`
 fi

}

function updatePerflog {

 #CPU dat file format
 #time %usr %sys %wio %idle

 sar -u 1 1|tail -1|awk '{print $1,$2,$3,$4,$5}' >> $CPUDAT

 #Mem dat file format
 #time inuse free pin virtual

 time=`date +%T`
 svmon -G|sed -e "s/memory/$time/"|sed -n '2p'|awk '{print $1,$3,$4,$5,$6}' >> $MEMDAT

 #Process dat file format
 #time inuse pin pgsp virtual
 if [ $JAVARun -eq 1 ]; then
 time=`date +%T`
 svmon -P $javapid | awk '($2 ~/java/){print $2,$3,$4,$5,$6}'|sed -e "s/java/$time/" >>\ 
     $JAVADAT
 fi

}

DATDIR=/perflog
CPUDAT=cpu.dat
MEMDAT=mem.dat
JAVADAT=java.dat
duration=30
interval=30
javapid=0
running=0
JAVARun=1

while getopts ":t:i:" opt
do
 case $opt in
 t) duration=$OPTARG;;
 i) interval=$OPTARG;;
 esac
done

#check process existence of java
checkProcess

rm -rf $DATDIR
mkdir -p $DATDIR
cd $DATDIR
touch $CPUDAT
touch $MEMDAT
if [ $JAVARun -eq 1 ]; then
touch $JAVADAT
fi

# 按照一定的间隔时间,在指定的时间内持续监测系统的性能数据
while [ $running -lt $duration ]
do
 updatePerflog
 sleep `expr $interval \* 60`
 running=`expr $running + $interval`
done

在 aixperfmonitor 脚本中,最重要的部分就是updatePerflog这个函数,它对 sar 和 svmon 的命令行输出进行处理以得到我们想要的性能数据。比如,对于系统 CPU 使用情况,我们抓取了 %usr, %sys, %wio, %idle 这四个性能参数;对于系统内存使用情况 , 我们抓取了 inuse, free, pin, virtual 这四个性能参数。另外,checkpProcess函数也值得我们注意,它检查相关进程是否真的存在,如果进程不存在,则不会在updatePerflog函数中抓取相关性能数据。

有了 aixperfmonitor.sh 脚本之后,我们就可以监测系统性能数据了。比如说,我们希望监测时间为 3 天,监测间隔为 10 分钟,那么我们可以通过下面的脚本完成调用:

bash-3.00# nohup ./aixperfmonitor.sh -t 4320 -i 10 2>&1 >/tmp/perfmonitor_output &


生成基于 WEB 的性能图表

有了性能监测数据以后,我们就可以开始利用 JFreeChart 来生成图表并且把它们发布到 WEB 上了。

首先,让我们利用 JFreeChart 来编写生成图表的 Java 代码。由于下载的 JfreeChart 包中带有丰富的例程,我们不需重头开始,只要对其中的例程加以修改即可。AIXPerfChart.java 包含了生成图表的全部代码。


清单 2 AIXPerfChart.java( 只显示部分源代码 )

public class AIXPerfChart {

 protected final static Pattern FILE_PATTERN = 
 Pattern.compile("([^\\/]+)\\.dat");
 
 protected final static Pattern DATA_LINE = 
 // 匹配数据文件的格式 , 每个 ([^\\s]+) 匹配数据文件中的一列 , 共 5 列 
 Pattern.compile("\\s*([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s*");

 // 返回以小时为单位的监测时间 
 private double getTimeInDouble (String ts) {
 String[] hms = ts.split(":");
 double t = (Double.parseDouble(hms[0]) + 
 Double.parseDouble(hms[1]) / 60.0 +
 Double.parseDouble(hms[2]) / 3600.0) ;
 if(duration >= 0.0) {
 if (lastTime > t) 
  duration += t + 24.0 - lastTime;
 else
 duration += t - lastTime; 
 } else {
 duration = 0.0;
 }
 lastTime = t;
 return duration; //by hours 
 }
 
 // 根据数据文件的名字来决定图表的 title, x 轴和 y 轴的标签 
 private void parseFileName() {
 String[] pathParts = dataFile.split("/");
 int len = pathParts.length;
 Matcher m = FILE_PATTERN.matcher(pathParts[len-1]);
 if (m.matches()) {
 chartType = m.group(1);
 }
 if (chartType.equals("cpu")) {
 series.add(new XYSeries("User"));
 series.add(new XYSeries("System"));
 series.add(new XYSeries("WaitIO"));
 series.add(new XYSeries("Idle"));
 title = "SYSTEM CPU";
  yAxisLabel = "Percentage";
 } else if (chartType.equals("mem")) {
 series.add(new XYSeries("Inuse"));
 series.add(new XYSeries("Free"));
 series.add(new XYSeries("Pin"));
 series.add(new XYSeries("Virtual"));
 title = "SYSTEM MEMORY";
  yAxisLabel = "pages";
 } else {
 series.add(new XYSeries("Inuse"));
 series.add(new XYSeries("Pin"));
 series.add(new XYSeries("Pgsp"));
 series.add(new XYSeries("Virtual"));
 title = chartType.toUpperCase();
 yAxisLabel = "pages";
 }
 }
 
 // 创建数据集
 private XYDataset createDataset() {

 XYSeries s1 = series.get(0); 
 XYSeries s2 = series.get(1); 
 XYSeries s3 = series.get(2); 
 XYSeries s4 = series.get(3); 
 try {
 if(!dataFile.startsWith("/")) { dataFile = workDir + "/" + dataFile; }
 BufferedReader in = 
 new BufferedReader(new FileReader(dataFile));
    String line;
    while((line = in.readLine()) != null) {
     Matcher m = DATA_LINE.matcher(line);
     if (m.matches()) {
     double x = getTimeInDouble(m.group(1)); 
     double y1 = getYValueInDouble(m.group(2)); 
     double y2 = getYValueInDouble(m.group(3)); 
     double y3 = getYValueInDouble(m.group(4)); 
     double y4 = getYValueInDouble(m.group(5)); 

     s1.add(x, y1); 
     s2.add(x, y2); 
     s3.add(x, y3);
     s4.add(x, y4); 
     } else {
     }
    }

 in.close();
 } catch (Exception e) {
    System.err.println(e.toString());
 }

 XYSeriesCollection dataset = new XYSeriesCollection();
 dataset.addSeries(s1);
 dataset.addSeries(s2);
 dataset.addSeries(s3);
   dataset.addSeries(s4);
 return dataset;
 }
}

在 AIXPerfChart.java 源文件当中,函数getTimeInDouble计算每个监测时间点距开始监测时经过的时间。由于命令行输出的时间点是以二十四小时制计量并且不含日期信息,因此如果当前的监测时间点小于前一个监测时间点,就表明当前时间已经进入新的一天。在计算监测时间的时候特别需要注意到这个因素,不然会得到错误的监测时间。至于具体的计算方法,请参照清单 2 中的代码。

另外,由于篇幅的关系,在清单 2 中没有列出函数createChartexportChartCreateChart通过调用createDataset函数生成数据集,然后生成图表 ,exportChart则把图表按照指定的图像文件格式导出为图像文件。在createChart中还可设定图表的相关属性,比如大小,背景颜色等等。

编写好 AIXPerfChart.java 后 , 让我们用下面的命令来进行编译 :

javac -cp ./jcommon-1.0.5.jar:./jfreechart-1.0.1.jar com/aix/chart/AIXPerfChart.java

编译成功后,我们今后可以通过 aixperfchart.sh 这个脚本来调用绘制图表的功能。


清单 3 aixperfchart.sh

#!/bin/sh

# 存放 AIXPerfChart.class 和 JFreeChart lib 的路径
AIX_CHART=/opt/aixperfmonitor/src

java -cp ${AIX_CHART}:${AIX_CHART}/jfreechart-1.0.1.jar:${AIX_CHART}/jcommon-1.0.5.jar \ 
com.aix.chart.AIXPerfChart $@

最后,我们来编写脚本 htmlreport.sh,它帮助我们定期把性能数据绘制成图表并发布到 WEB 服务器上。


清单 4 htmlreport.sh( 只显示部分源代码 )

############################################################## 
# 通过 STAF 从 AIX 机器上获取性能数据,/perflog 为性能数据文件在 AIX 机器上的默认存放目录 #
##############################################################

ret=`staf $server process start shell command "staf local fs copy directory /perflog \

todirectory $dataDir tomachine 9.168.0.2" workdir /tmp wait returnstdout returnstderr`

##########################################################   
# 根据性能数据文件绘制图表 #
###########################################################

aixperfchart.sh mem.dat $dataDir $imgFormat
aixperfchart.sh cpu.dat $dataDir $imgFormat
charts[0]="mem.$imgFormat"
charts[1]="cpu.$imgFormat"
index=2

cd $dataDir

# 如果有多个进程的数据文件 , 逐一绘制相应的图表
images=`ls *.dat|grep -v mem|grep -v cpu`

for img in $images; do
 aixperfchart.sh $img $dataDir $imgFormat
 charts[$index]="${img%%.*}.$imgFormat"
 let "index=$index+1"
done

##########################################################
# 生成包含性能图表的 html 文件 , 并发布到 WEB 上 #
##########################################################

#
htmlfn="${dataDir}/perfchart.html"
echo "<html><head></head><body>" > $htmlfn
if [ -z $server ]; then
 echo "<h2> Perf Charts</h2>" >> $htmlfn
else
 echo "<h2> $server Perf Charts</h2>" >> $htmlfn
fi
echo "<table cellpadding=\"3\" cellspacing=\"0\">" >> $htmlfn
curIndex=0
for (( curIndex=0; curIndex < $index; curIndex++ )) ; do
 let "i = $curIndex % 2"
 if [ "$i" -eq 0 ] ; then
 echo "<tr>" >> $htmlfn
 fi
 imageFile=${charts[$curIndex]}
 dataFile="${imageFile%%.*}.dat"
 echo "<td align="center"><img src=\"${charts[$curIndex]}\" width=600 height=320/>\
 <br/><a href= \"${dataFile}\">${dataFile}</a></td>" >> $htmlfn

 if [ "$i" -eq 1 ] ; then
 echo "</tr>" >> $htmlfn
 fi
done

echo "</table></body></html>" >> $htmlfn

在脚本 htmlreport.sh 中有两个地方值得我们注意。一个是调用 STAF 的 FS service 把性能数据文件从 AIX 机器拷贝到 Linux 机器上。为方便起见,建议直接把数据文件拷贝到 web 服务器的发布目录,这样就不需要在发布性能数据及图表时再次拷贝了。另外一个是绘制图表的代码,我们把生成的图表文件名存储在 charts 数组中。考虑到读者可能需要监测多个进程,代码并没有只是简单生成 java 进程的图表,而是逐一为可能存在的进程生成图表并且存储到 charts 数组中。

有了 htmlreport.sh 脚本之后,我们就可以用下面的命令调用这个脚本让它定期绘制图表,并把图表发布到 WEB 服务器。

bash-3.00# nohup ./htmlreport.sh -t <duration> -i <interval> 2>&1 \
>/tmp/htmlreport &

假定性能数据以及图表被发布到 web 服务器的 perflog 目录,那么打开浏览器,输入下面的 URL,我们就能看到监测数据的图表了。

http://9.168.0.2/perflog/perfchart.html


图 2 显示性能图表的 web 页面


结束语

在本文中,我介绍了如何利用 AIX 系统自带的性能工具包和 JFreeChart 图表库去构建一个简单易用的性能监测工具。通过简单的扩展,这个工具可以完成更多的监测功能,比如说,监测磁盘使用情况,监测 IO 使用情况,等等。


参考资料

学习

获得产品和技术

  • IBM 试用软件:从 developerWorks 可直接下载这些试用软件,您可以利用它们开发您的下一个项目。

讨论

关于作者 

戴建武,IBM 测试工程师,现在在 IBM CDL 语音组从事 Webshpere Voice Server 的系统测试工作。

 

 


TAG:

 

评分:0

我来说两句

Open Toolbar