Web網站效能體現在併發使用者數已經網站的吞吐量和時延。
最簡單的壓力測試工具就是ab "Apache Benchmark"
下面將介紹ab的安裝和使用:
1. ab的安裝
ab的安裝非常簡單,安裝了httpd,就自帶ab
CentOS下的安裝:
yum install -y httpd
Ubuntu下的安裝:
apt-get install apache2
安裝好後,就可以使用ab了。
2. ab使用前的準備工作
由於ab是壓力測試工具,我們需要把允許開啟檔案的數量調大。可以修改/etc/security/limits.conf
echo "* soft nofile 65535" >> /etc/security/limits.conf;echo "* hard nofile 65535" >> /etc/security/limits.conf
更改了這個配置後,需要重新啟動VM。
或者採用臨時命令:
ulimit -n 65535
這樣更改不需要重啟機器。
3. 執行ab,或wrk
網上有很多ab和wrk使用的介紹,這裡就不細講了。一般打流量的命令是:
ab -c 5000 -r -n 40000000 http://xx.xx.xx.xx/
其中-c表示併發連線數;-n表示總共的請求數量;-r表示出現錯誤不退出,這個引數可以保證測試的連續性。注意http連結最後一定要是"/",否則報錯。
wrk -t1 -c6000 -d2000s http://x.x.x.x/
4. 指令碼
為了保證測試的連續性,下面的小指令碼可以檢測ab測試程式是否在執行。如果有,表示正在測試,等待10s,繼續檢測;如果沒有,表示ab已經測試結束,需要重新啟動。具體指令碼如下:
#!/bin/bash while true do flag=`ps -ef | grep "ab -c" | grep -v grep| wc -l` [ "$flag" = 1 ] && continue || ab -c 5000 -r -n 40000000 http://x.x.x.x/ sleep 10 done
wrk的指令碼如下
#!/bin/bash while true do flag=`ps -ef | grep "wrk -t" | grep -v grep| wc -l` [ "$flag" = 1 ] && continue || /root/wrk-master/wrk -t1 -c6000 -d2000s http://x.x.x.x/ sleep 10 done
把此指令碼後臺執行。
5. 時延測試
在伺服器壓力上去後,伺服器的頻寬和時延的檢測成為檢測伺服器能力的指標之一。
頻寬的檢測,可以採用nload、Zabbix等工具。
時延的檢測,也可以採用Zabbix等帶外方式。本文采用的是比較簡單的time工具。
由於time和一般的Shell命令不同,grep、awk等語句不能正常的抓取執行結果。我們一般採用把執行結果輸出到檔案,再檢索檔案的方式。並且time的重定向是stderr的定向。具體命令是:
(time -p curl http://x.x.x.x > /dev/null) &>> out.txt
然後再採用grep real out.txt來獲取時延。
6. 時延指令碼
可以通過下面的指令碼收集時延:
#!/bin/bash while true do (time -p curl http://x.x.x.x > /dev/null) &> out.txt grep real out.txt | awk '{print $0 "\t" strftime()}' >> delay.txt sleep 10 done
7. 伺服器端檢視同時線上人數的命令
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'
結果如下:
TIME_WAIT t 32502
FIN_WAIT1 t 4171
FIN_WAIT2 t 267
ESTABLISHED t 993
SYN_RECV t 610
CLOSING t 274
LAST_ACK t 1
或者用下面的命令:
netstat -s | grep "connections established"
4288 connections established
8. 通過curl統計時延插入資料庫
#!/bin/bash while true do (time -p curl http://x.x.x.x > /dev/null) &> out.txt grep real out.txt | awk '{print $0 "\t" strftime()}' >> delay.txt time=$(TZ=Asia/Shanghai date "+%Y-%m-%d %H:%M:%S") webDelay=`grep real out.txt | awk '{print $2}'` hostn=`hostname` mysql -hxxxx -uxxxx -pxxxx -e "use delay; insert into delay2 (delay, time, host) values($webDelay,'$time','$hostn');" sleep 20 done
8.1 通過python指令碼把時延插入資料庫
#!/usr/bin/env python import StringIO import pycurl import sys import os import time import MySQLdb import socket def getHTTPTime(url): crl = pycurl.Curl() #crl.setopt(pycurl.VERBOSE,1) crl.setopt(pycurl.FOLLOWLOCATION, 1) crl.setopt(pycurl.MAXREDIRS, 5) crl.fp = StringIO.StringIO() crl.setopt(pycurl.URL, url) crl.setopt(crl.WRITEFUNCTION, crl.fp.write) p = crl.perform() time = crl.getinfo(pycurl.TOTAL_TIME) return time url = "http://xx.xx.xx.xx/" myhost = socket.gethostname() host="xxx.mysqldb.chinacloudapi.cn" user="xxx" passwd="xxxxxx" db="delay" port=3306 try: conn=MySQLdb.connect(host=host,user=user,passwd=passwd,port=port) conn.select_db(db) conn.select_db(db) cur=conn.cursor() while True: curtime=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) mytime = float(getHTTPTime(url)) T = [] T.append(mytime) T.append(curtime) T.append(myhost) cur.execute('insert into delay10 (delay, time, host) values(%s,%s,%s)',T); conn.commit() #aa=cur.execute('select id,delay,time from delay10') #print aa #for data in cur.fetchall(): # print data time.sleep(60) except MySQLdb.Error,e: print "Mysql Error %d: %s" % (e.args[0], e.args[1])
9. 通過paping檢測時延,並插入資料庫
#!/bin/bash while true do getDelay=`/root/paping -p 80 -c 1 x.x.x.x | grep time= | awk '{print $4}' | awk 'BEGIN{FS="="} {print $2}'` time=$(TZ=Asia/Shanghai date "+%Y-%m-%d %H:%M:%S") #webDelay=`echo ${a%ms*}` [ $getDelay ] && webDelay=$getDelay || webDelay=1000 hostn=`hostname` mysql -hhwdelay.mysqldb.chinacloudapi.cn -uhwdelay%hengwei -pabc@123456 -e "use delay; insert into delay4 (delay, time, host) values('$webDelay','$time','$hostn');" sleep 20 done
10. php頁面反應實際時延情況:
<?php echo "xxx時延測試</br>"; echo "大於1秒鐘時延的統計"; $mysql_server_name="xxxxxx"; //資料庫伺服器名稱 $mysql_username="xxxxx"; // 連線資料庫使用者名稱 $mysql_password="xxxxx"; // 連線資料庫密碼 $mysql_database="delay"; // 資料庫的名字 // 連線到資料庫 $conn=mysql_connect($mysql_server_name, $mysql_username, $mysql_password); // 從表中提取資訊的sql語句 $strsql="select * from delay2 where delay > 1 order by id desc"; // 執行sql查詢 $result=mysql_db_query($mysql_database, $strsql, $conn); // 獲取查詢結果 $row=mysql_fetch_row($result); echo '<font face="verdana">'; echo '<table border="1" cellpadding="1" cellspacing="2">'; // 顯示欄位名稱 echo "</b><tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++) { echo '<td bgcolor="#FF0000"><b>'. mysql_field_name($result, $i); echo "</b></td></b>"; } echo "</tr></b>"; // 定位到第一條記錄 mysql_data_seek($result, 0); // 迴圈取出記錄 while ($row=mysql_fetch_row($result)) { echo "<tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++ ) { echo '<td bgcolor="#00FF00">'; echo $row[$i]; echo '</td>'; } echo "</tr></b>"; } echo "</table></b>"; echo "</font>"; // 釋放資源 mysql_free_result($result); // 關閉連線 mysql_close($conn); ?>
11. 多監測點合併網頁:
<!DOCTYPE html> <html> <head> <title>HWTEST.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"/> <meta http-equiv="description" content="this is my page"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" type="text/css" href="./test.css"> </head> <body> <!-- Logo div --> <div class="logo"> <h1>xxx時延測試比較頁面</h1> </div> <!-- Adv div --> <div class="ad"> <div class="stuad"> <h4>Azure上海VM檢測Azure北京VM時延</br></h4> <h4>大於1秒鐘時延的統計</h4> <?php $mysql_server_name="xxx.chinacloudapi.cn"; //資料庫伺服器名稱 $mysql_username="xxx"; // 連線資料庫使用者名稱 $mysql_password="xxx"; // 連線資料庫密碼 $mysql_database="delay"; // 資料庫的名字 // 連線到資料庫 $conn=mysql_connect($mysql_server_name, $mysql_username, $mysql_password); // 從表中提取資訊的sql語句 $strsql="select id,delay,time from delay2 where delay > 1 order by id desc"; //$strsql="select * from delay2 where delay > 1 order by id desc"; // 執行sql查詢 $result=mysql_db_query($mysql_database, $strsql, $conn); // 獲取查詢結果 $row=mysql_fetch_row($result); echo '<font face="verdana">'; // echo '<table border="1" cellpadding="1" cellspacing="2">'; echo '<table border="1" cellpadding="1" cellspacing="2" align="center">'; // 顯示欄位名稱 echo "</b><tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++) { echo '<td bgcolor="#FF0000"><b>'. mysql_field_name($result, $i); echo "</b></td></b>"; } echo "</tr></b>"; // 定位到第一條記錄 mysql_data_seek($result, 0); // 迴圈取出記錄 while ($row=mysql_fetch_row($result)) { echo "<tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++ ) { echo '<td bgcolor="#00FF00">'; echo $row[$i]; echo '</td>'; } echo "</tr></b>"; } echo "</table></b>"; echo "</font>"; // 釋放資源 mysql_free_result($result); // 關閉連線 mysql_close($conn); ?> </div> <div class="ad2"> <h4>家中採用curl檢測頁面時延</br></h4> <h4>大於1秒鐘時延的統計</h4> <?php $mysql_server_name="xxx.chinacloudapi.cn"; //資料庫伺服器名稱 $mysql_username="xxx"; // 連線資料庫使用者名稱 $mysql_password="xxx"; // 連線資料庫密碼 $mysql_database="delay"; // 資料庫的名字 // 連線到資料庫 $conn=mysql_connect($mysql_server_name, $mysql_username, $mysql_password); // 從表中提取資訊的sql語句 $strsql="select id,delay,time from delay3 where delay > 1 order by id desc"; // 執行sql查詢 $result=mysql_db_query($mysql_database, $strsql, $conn); // 獲取查詢結果 $row=mysql_fetch_row($result); echo '<font face="verdana">'; // echo '<table border="1" cellpadding="1" cellspacing="2">'; echo '<table border="1" cellpadding="1" cellspacing="2" align="center" >'; // 顯示欄位名稱 echo "</b><tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++) { echo '<td bgcolor="#FF0000"><b>'. mysql_field_name($result, $i); echo "</b></td></b>"; } echo "</tr></b>"; // 定位到第一條記錄 mysql_data_seek($result, 0); // 迴圈取出記錄 while ($row=mysql_fetch_row($result)) { echo "<tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++ ) { echo '<td bgcolor="#00FF00">'; echo $row[$i]; echo '</td>'; } echo "</tr></b>"; } echo "</table></b>"; echo "</font>"; // 釋放資源 mysql_free_result($result); // 關閉連線 mysql_close($conn); ?> </div> <div class="house"> <h4>家中採用paping測試</br></h4> <h4>大於100ms時延的統計</h4> <?php $mysql_server_name="xxx.chinacloudapi.cn"; //資料庫伺服器名稱 $mysql_username="xxx"; // 連線資料庫使用者名稱 $mysql_password="xxx"; // 連線資料庫密碼 $mysql_database="delay"; // 資料庫的名字 // 連線到資料庫 $conn=mysql_connect($mysql_server_name, $mysql_username, $mysql_password); // 從表中提取資訊的sql語句 $strsql="select id,delay,time from delay4 where delay > 100 order by id desc"; // 執行sql查詢 $result=mysql_db_query($mysql_database, $strsql, $conn); // 獲取查詢結果 $row=mysql_fetch_row($result); echo '<font face="verdana">'; // echo '<table border="1" cellpadding="1" cellspacing="2">'; echo '<table border="1" cellpadding="1" cellspacing="2" align="center" >'; // 顯示欄位名稱 echo "</b><tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++) { echo '<td bgcolor="#FF0000"><b>'. mysql_field_name($result, $i); echo "</b></td></b>"; } echo "</tr></b>"; // 定位到第一條記錄 mysql_data_seek($result, 0); // 迴圈取出記錄 while ($row=mysql_fetch_row($result)) { echo "<tr></b>"; for ($i=0; $i<mysql_num_fields($result); $i++ ) { echo '<td bgcolor="#00FF00">'; echo $row[$i]; echo '</td>'; } echo "</tr></b>"; } echo "</table></b>"; echo "</font>"; // 釋放資源 mysql_free_result($result); // 關閉連線 mysql_close($conn); ?> </div> </div> </body> </html>
CSS檔案:
body{ width:950px; margin: 0 auto; background-color: white; border: 1px solid red; font-size: 16px; } .logo{ width: 950px; height: 68px; background-color: yellow; float: left; margin-top: 5px; text-align: center; } .ad{ width: 950px; /*height: 212px;*/ /*background-color: pink;*/ margin-top: 5px; float: left; } .stuad{ width: 310px; /*height: 196px;*/ float: left; background-color: #ADFEDC; margin: 4px 0 0 4px; text-align: center; } .ad2{ width: 310px; /*height: 196px;*/ float: left; background-color: #D2A2CC; margin: 4px 0 0 4px; text-align: center; } .house{ width: 310px; /*height: 196px;*/ float: left; background-color: #FC7E8C; margin: 4px 0 0 4px; text-align: center; }
12. 檢測程式是否執行的指令碼
#!/bin/bash while true do cflag=`ps -ef | grep delay.sh | grep -v grep | wc -l` pflag=`ps -ef | grep mypachk.sh | grep -v grep | wc -l` echo $cflag $pflag #[ "$flag" = 1 ] && continue || /root/delay.sh & [ "$cflag" = 0 ] && /root/delay.sh || echo "curl is ok" >> record.txt [ "$pflag" = 0 ] && /root/mypachk.sh || echo "paping is ok" >> record.txt sleep 600 done