公司最近要使用CDN,为了能测试下在加入CDN后的效果,需要对网站做一个基准测试。以下是实现方式。


以下是对网站数据的采集,使用screen运行php index.php


index.php

<?php

include(__DIR__.'/mysql.php');
include(__DIR__.'/config.php');
include(__DIR__.'/helper.php');

while(1)
{
	$db = new Mysql();
	$db->connect($config['db']);
	$create_time = strtotime(date('Y-m-d H:i',time()));
		
	//######################2M图片#############################
	//无CDN
	$start = get_microtime();
	$status = curl('http://27.54.226.101:99/scenicInt/0/6/2/101062/101062.jpg');
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,1,2,$create_time)");
	
	//使用CDN
	$start = get_microtime();
	$status = curl('http://image.yhiker.com/scenicInt/0/6/2/101062/101062.jpg');
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,1,1,$create_time)");
	
	//######################12M离线包#############################
	//无CDN
	$start = get_microtime();
	$status = curl("http://27.54.226.101:99/0086/itinerary/01000000379-0.zip");
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,2,2,$create_time)");
	
	//使用CDN
	$start = get_microtime();
	$status = curl("http://image.yhiker.com/0086/itinerary/01000000379-0.zip");
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,2,1,$create_time)");
	
	
	//######################API接口数据#############################
	//无CDN
	$start = get_microtime();
	$status = curl('http://27.54.226.101:98/haiyouapi/services',array('command'=>8101,'platformType'=>'web','param'=>array('itineraryId'=>'01000000599')));
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,3,2,$create_time)");
	
	//使用CDN
	$start = get_microtime();
	$status = curl('http://api.yhiker.com/haiyouapi/services',array('command'=>8101,'platformType'=>'web','param'=>array('itineraryId'=>'01000000599')));
	$end = get_microtime();
	$time = sprintf("%s",($end - $start));
	if( !$status )
	{
		$time = -1;
	}
	$db->ping($config['db']);
	$db->query("insert into benchmark(time,type,category,create_time) value($time,3,1,$create_time)");
	
	unset($start);
	unset($status);
	unset($end);
	unset($time);
	unset($db);
	sleep(120);
}
?>

config.php

<?php

header('Content-type:text/html;charset=utf-8');
ini_set('date.timezone','Asia/Shanghai');
set_time_limit(0);
error_reporting(E_ERROR);
ini_set('memory_limit', '1024M');

$config['db'] = array
(
    'host'      => '192.168.1.188:3000',
    'user'      => 'xupeng',
    'pass'      => 'xupeng',
    'db'        => 'test',
    'pconnect'  => false,
    'dbcharset' => 'utf8',
);
helper.php

<?php
function get_microtime()
{
    list($usec, $sec) = explode(' ', microtime());
    return ((float)$usec + (float)$sec);
}

function curl($url, $data = array(), $timeout = 20)
{
	$ch = curl_init();
	if (is_array($data) && $data)
	{
		$formdata = json_encode($data);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		curl_setopt($ch, CURLOPT_POSTFIELDS, $formdata);
	}
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
	$result   = curl_exec($ch);
	$response = curl_getinfo( $ch );
	curl_close($ch);
	if( $response['http_code'] == 200 )
	{
		return true;
	}
	else
	{
		return false;
	}
}
mysql.php

<?php

class mysql
{
	var $dbhost;		//数据库地址
	var $dbuser;		//数据库用户名
	var $dbpasswd;		//数据库密码
	var $dbpconnect=0;	//数据库长连接
	var $dbname;		//数据库名称
	var $dbchart;		//数据库链接编码
	var $dblink;		//数据库连接对象
	var $sql;			//sql语句
	var $res;			//sql语句执行结果
	var $errno;			//错误信息		
 
	function connect($dbConfig)
	{
		$this->dbhost = $dbConfig['host'];
		$this->dbuser = $dbConfig['user'];
		$this->dbpasswd = $dbConfig['pass'];
		$this->dbpconnect = $dbConfig['pconnect'];
		$this->dbname = $dbConfig['db'];
		$this->dbchart = $dbConfig['dbcharset'];
		if($this->dbpconnect)
		{
			$this->dblink = mysql_pconnect($this->dbhost,$this->dbuser,$this->dbpasswd,1) or die('can not connect to mysql database!');
		}
		else
		{
			$this->dblink = mysql_connect($this->dbhost,$this->dbuser,$this->dbpasswd,1) or die('can not connect to mysql database!');
		}
		mysql_query('set names '.$this->dbchart, $this->dblink);
		mysql_select_db($this->dbname, $this->dblink);
		unset($dbConfig);
	}
 
	/**
	 * 数据库执行语句
	 *
	 * @return blooean
	 *
	 */
	function query($sql, $die_msg = 1)
	{
		$this->sql = $sql;
		$result = @mysql_query($sql, $this->dblink); //可以用自定义错误信息的方法,就要压制本身的错误信息
		if($result == true)
		{
			return $result;
		}
		else
		{
			//有错误发生
			$this->errno = mysql_errno($this->dblink);
			if($this->errno >0)
			{
				if($die_msg == 1)
				{
					//强制报错并且die
					$this->msg($sql);
				}
				else
				{
					return $this->errno;//无强制报错,则返回错误代码
				}
			}
		}
	}
 
	/**
	 * 获得查询语句单条结果
	 *
	 * @return array
	 * 
	 */
	function get_one($sql)
	{
		$this->sql = $sql;
		$this->res = $this->query($sql);
		return mysql_fetch_assoc($this->res);
	}
 
	/**
	 * 获得查询语句多条结果
	 *
	 * @return array
	 * 
	 */
	function get_all($sql,$filed=null)
	{
		$this->sql = $sql;
		$this->res = $this->query($sql);
		$arr = array();
		while($row = mysql_fetch_assoc($this->res))
		{
			if( $filed )
			{
				$arr[] = $row[$filed];	
			}
			else
			{
				$arr[] = $row;
			}
		}
		return $arr;
	}
 
	/**
	 * 取得结果数据
	 *
	 * @param resource $query
	 *
	 * @return string
	 *
	 */
	function result($query, $row)
	{
		$query = @mysql_result($query, $row);
		return $query;
	}
	
	function affected_rows()
	{
		return mysql_affected_rows($this->dblink);
	}	
 
	/**
	 * 获得刚插入数据的id
	 *
	 * @return int id
	 *
	 */
	function insert_id()
	{
		return ($id = mysql_insert_id($this->dblink)) >= 0 ? $id : $this->result($this->query('SELECT last_insert_id()'), 0);
	}
 
	/**
	 * 关闭数据库连接,当您使用持续连接时该功能失效
	 *
	 * @return blooean
	 *
	 */
	function close()
	{
		return mysql_close($this->dblink);
	}
	
	function ping($dbconfig)
	{
		if(!mysql_ping($this->dblink))
		{
			$this->close();
			$this->connect($dbconfig); 
		}
	}	
 
	/**
	 * 显示自定义错误
	 *
	 */
	function msg($sql)
	{
		if($this->errno) {
			//可以根据错误ID,配置好一些友好的错误信息提示语句
			$msgArr = array();
			$msgArr['1062'] = "唯一性索引有重复值插入";
			/*...更多错误代码根据实际业务再添加...*/
			if($msgArr[$this->errno]) {
				$errMsg = $msgArr[$this->errno];//已定义的错误
			}else{
				$errMsg = mysql_error();//未定义的错误,由默认的错误信息决定
			}
			echo "数据库操作错误\n";
			echo "错误代码:".$this->errno."\n";
			echo "SQL语句:".$sql."\n";
			echo "错误信息:".$errMsg."\n";
			echo date('Y-m-d H:i:s',time())."\n";

			unset($msgArr);
			die;
		}
	}
 
    function __destruct()
	{
		$this->dbhost;
		$this->dbuser;
		$this->dbpasswd;
		$this->dbpconnect;
		$this->dbname;
		$this->dbchart;
		$this->dblink;
		$this->sql;
		$this->res;
		$this->errno;
	}
 
 
}

以下是数据报表的展示:

<?php 
	include(__DIR__.'/config.php');
	include(__DIR__.'/mysql.php');
	
	$db = new mysql();
	$db->connect($config['db']);
	
	$result = $db->get_all("select * from benchmark where category = 2 order by create_time desc limit 90");
	//echo count($result);exit;
	$ret = array();
	$total = array();
	foreach( array_reverse($result) as $v)
	{
		$time_db = strtotime(date('Y-m-d H:i',$v['create_time']));
		$time = intval(($time_db+28800).'000');
		$ret[$v['type']] .= '['.$time.','.$v['time'].'],';	
		$total[$v['type']][] = ( $v['time'] > 0 ) ? $v['time'] : 0;
	}
	$pic = '['.chop($ret[1],',').']';
	$zip = '['.chop($ret[2],',').']';
	$api = '['.chop($ret[3],',').']';
	
	$pic_average =  array_sum($total[1]) / count($total[1]);
	$zip_average =  array_sum($total[2]) / count($total[2]);
	$api_average =  array_sum($total[3]) / count($total[3]);
	
	//CDN
	$result_cdn = $db->get_all("select * from benchmark where category = 1 order by create_time desc limit 90");
	$ret_cdn = array();
	$total_cdn = array();
	foreach( array_reverse($result_cdn) as $v)
	{
		$time_db = strtotime(date('Y-m-d H:i',$v['create_time']));
		$time = intval(($time_db+28800).'000');
		$ret_cdn[$v['type']] .= '['.$time.','.$v['time'].'],';	
		$total_cdn[$v['type']][] = ( $v['time'] > 0 ) ? $v['time'] : 0;
	}
	$pic_cdn = '['.chop($ret_cdn[1],',').']';
	$zip_cdn = '['.chop($ret_cdn[2],',').']';
	$api_cdn = '['.chop($ret_cdn[3],',').']';
	
	$pic_average_cdn =  array_sum($total_cdn[1]) / count($total_cdn[1]);
	$zip_average_cdn =  array_sum($total_cdn[2]) / count($total_cdn[2]);
	$api_average_cdn =  array_sum($total_cdn[3]) / count($total_cdn[3]);
	
	
	$all = $db->get_all("select sum(time) as sum,sum(item) as id from benchmark where time != -1 and category = 2 GROUP BY type");
	$pic_all_average =  $all[0]['sum'] / $all[0]['id'];
	$zip_all_average =  $all[1]['sum'] / $all[1]['id'];
	$api_all_average =  $all[2]['sum'] / $all[2]['id'];
	
	
	$all_cdn = $db->get_all("select sum(time) as sum,sum(item) as id from benchmark where time != -1 and category = 1 GROUP BY type");
	$pic_all_average_cdn =  $all_cdn[0]['sum'] / $all_cdn[0]['id'];
	$zip_all_average_cdn =  $all_cdn[1]['sum'] / $all_cdn[1]['id'];
	$api_all_average_cdn =  $all_cdn[2]['sum'] / $all_cdn[2]['id'];
?>
<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>国内服务器基准测试</title>

		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
		<script type="text/javascript">
		$(function () {
			$('#container_pic').highcharts({
				chart: {
					type: 'areaspline'
				},
				title: {
					text: '2M图片速度测试'
				},
				//subtitle: {
				//	text: '没有CDN加速国内访问速度'
				//},
				xAxis: {
					type: 'datetime',
					labels: {
						formatter: function() {
							return  Highcharts.dateFormat('%H:%M', this.value);
						}
					}
				},
				yAxis: {
					title: {
						text: '访问速度'
					}
				},
				tooltip: {
					shared: true,
					dateTimeLabelFormats:{
						day: '%Y-%m-%d %H:%M'
					},
					valueSuffix: 's'
				},
				credits: {
					enabled: false
				},
				plotOptions: {
					areaspline: {
						fillOpacity: 0.5
					}
				},
				series: [{
					name: '无CDN加速',
					data: <?php echo $pic;?>
				},{
					name: '有CDN加速',
					data: <?php echo $pic_cdn;?>
				}]
			});
			
			$('#container_zip').highcharts({
				chart: {
					type: 'areaspline'
				},
				title: {
					text: '12M离线包速度测试'
				},
				//subtitle: {
				//	text: '没有CDN加速国内访问速度'
				//},
				xAxis: {
					type: 'datetime',
					labels: {
						formatter: function() {
							return  Highcharts.dateFormat('%H:%M', this.value);
						}
					}
				},
				yAxis: {
					title: {
						text: '访问速度'
					}
				},
				tooltip: {
					shared: true,
					dateTimeLabelFormats:{
						day: '%Y-%m-%d %H:%M'
					},
					valueSuffix: 's'
				},
				credits: {
					enabled: false
				},
				plotOptions: {
					areaspline: {
						fillOpacity: 0.5
					}
				},
				series: [{
					name: '无CDN加速',
					data: <?php echo $zip;?>
				},{
					name: '有CDN加速',
					data: <?php echo $zip_cdn;?>
				}]
			});		

			$('#container_api').highcharts({
				chart: {
					type: 'areaspline'
				},
				title: {
					text: 'API接口速度测试'
				},
				//subtitle: {
				//	text: '没有CDN加速国内访问速度'
				//},
				xAxis: {
					type: 'datetime',
					labels: {
						formatter: function() {
							return  Highcharts.dateFormat('%H:%M', this.value);
						}
					}
				},
				yAxis: {
					title: {
						text: '访问速度'
					}
				},
				tooltip: {
					shared: true,
					dateTimeLabelFormats:{
						day: '%Y-%m-%d %H:%M'
					},
					valueSuffix: 's'
				},
				credits: {
					enabled: false
				},
				plotOptions: {
					areaspline: {
						fillOpacity: 0.5
					}
				},
				series: [{
					name: '无CDN加速',
					data: <?php echo $api;?>
				},{
					name: '有CDN加速',
					data: <?php echo $api_cdn;?>
				}]
			});			
		});
		</script>
	</head>
	<body>
		<div id="container_pic" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
		<br />
		<div id="container_zip" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
		<br />
		<div id="container_api" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
		<br />
		<hr>
		<h1 style="text-align:center">无CDN访问速度</h1>
		<hr>
		<div style="margin-top:20px;">
			<h2>访问2M图片最近一小时内平均速度为:<?php echo $pic_average;?>s</h2>
			<h2>访问12M离线包最近一小时内平均速度为:<?php echo $zip_average;?>s</h2>
			<h2>访问api接口最近一小时内平均速度为:<?php echo $api_average;?>s</h2>
		</div>
		<div style="margin-top:30px;">
			<h2>访问2M图片平均速度为:<?php echo $pic_all_average;?>s</h2>
			<h2>访问12M离线包平均速度为:<?php echo $zip_all_average;?>s</h2>
			<h2>访问api接口平均速度为:<?php echo $api_all_average;?>s</h2>
		</div>
		<hr>
		<h1 style="text-align:center">有CDN访问速度</h1>
		<hr>
		<div style="margin-top:20px;">
			<h2>访问2M图片最近一小时内平均速度为:<?php echo $pic_average_cdn;?>s</h2>
			<h2>访问12M离线包最近一小时内平均速度为:<?php echo $zip_average_cdn;?>s</h2>
			<h2>访问api接口最近一小时内平均速度为:<?php echo $api_average_cdn;?>s</h2>
		</div>
		<div style="margin-top:30px;">
			<h2>访问2M图片平均速度为:<?php echo $pic_all_average_cdn;?>s</h2>
			<h2>访问12M离线包平均速度为:<?php echo $zip_all_average_cdn;?>s</h2>
			<h2>访问api接口平均速度为:<?php echo $api_all_average_cdn;?>s</h2>
		</div>
	</body>
	<script src="js/highcharts.js"></script>
	<script src="js/modules/exporting.js"></script>
</html>
数据库结构:

CREATE TABLE `benchmark` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `time` float NOT NULL,
  `type` tinyint(3) unsigned NOT NULL COMMENT '1:图片 2:zip 3:api',
  `category` tinyint(3) unsigned NOT NULL COMMENT '1:cdn 2:无cdn',
  `create_time` int(10) unsigned NOT NULL,
  `item` tinyint(3) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=27202 DEFAULT CHARSET=utf8;