第七周作业
发布于: 2020 年 07 月 23 日
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
压测时由于已经经过了性能测试和负载测试的阶段,系统在资源占用且无法合理释放的情况下,处理并发请求的能力会迅速下降,对于单个请求的响应时间会迅速增加,吞吐量也会迅速下降。
用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
class TestController extends Controller{ const user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'; function actionRun($url, $method, $data, $async_count, $times) { $request = [ 'method' => $method, 'url' => $url, 'referer' => '', 'data' => $data ]; $elapseds = []; echo '---- url: ' . $url . ' ---- async count: ' . $async_count . ' ---- times: ' . $times . "\r\n"; for ($i = 0; $i < $times; $i++) { echo '---- time: ' . $i; $start = microtime(true); $this->multi_curl($request, $async_count); $elapsed = microtime(true) - $start; $elapseds[] = $elapsed; echo ' ---- elapsed: ' . $elapsed . "\r\n"; } sort($elapseds, SORT_NUMERIC); $percent_index = intval($times * 0.95); $percent_elapsed = $elapseds[$percent_index - 1]; $avg_elapsed = array_sum($elapseds) / count($elapseds); echo '---- 95%: ' . $percent_elapsed . '---- index: ' . $percent_index . '---- avg: ' . $avg_elapsed . "\r\n"; } function multi_curl($request, $async_count) { $mh = curl_multi_init(); for ($i = 0; $i < $async_count; $i++) { $default = [ 'method' => 'GET', 'user-agent' => self::user_agent, 'url' => null, 'referer' => 'https://www.google.co.uk', 'headers' => null, 'data' => [], 'proxy' => false, 'timeout' => 15 ]; $request = array_merge($default, $request); $method = mb_strtolower($request['method']); $method_allow = ['get', 'post']; if (null === $request['url'] || !in_array($method, $method_allow, true)) { continue; } $options = [ CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => $request['user-agent'], CURLOPT_REFERER => $request['referer'], CURLOPT_TIMEOUT => $request['timeout'], CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_RETURNTRANSFER => 1, ]; if ($method == 'get') { $options[CURLOPT_HTTPGET] = true; $options[CURLOPT_URL] = self::buildUrl($request['url'], $request['data']); } elseif ($method == 'post') { $options[CURLOPT_URL] = $request['url']; $options[CURLOPT_POST] = true; $content_type = isset($request['headers']) && isset($request['headers']['Content-Type']) ? $request['headers']['Content-Type'] : null; $options[CURLOPT_POSTFIELDS] = self::buildPostData($request['data'], $content_type); } // headers if (isset($request['headers'])) { $http_headers = []; foreach ($request['headers'] as $k => $v) { $http_headers[] = $k . ':' . $v; } $options[CURLOPT_HTTPHEADER] = $http_headers; } $nor_curl = curl_init(); curl_setopt_array($nor_curl, $options); curl_multi_add_handle($mh, $nor_curl); //2 增加句柄 } $active = null; do { while (($mrc = curl_multi_exec($mh, $active)) == CURLM_CALL_MULTI_PERFORM) ; if ($mrc != CURLM_OK) { break; } // a request was just completed -- find out which one while ($done = curl_multi_info_read($mh)) { // get the info and content returned on the request $info = curl_getinfo($done['handle']); $error = curl_error($done['handle']); if (!isset($error) || empty($error)) { $content = curl_multi_getcontent($done['handle']); } else { echo 'url: ' . $info['url'] . ' error: ' . $error; } // remove the curl handle that just completed curl_multi_remove_handle($mh, $done['handle']); curl_close($done['handle']); } // Block for data in / output; error handling is done by curl_multi_exec if ($active > 0) { curl_multi_select($mh); } } while ($active); return; } private static function buildUrl($url, $mixed_data = '') { $query_string = ''; if (!empty($mixed_data)) { $query_mark = strpos($url, '?') > 0 ? '&' : '?'; if (is_string($mixed_data)) { $query_string .= $query_mark . $mixed_data; } elseif (is_array($mixed_data)) { $query_string .= $query_mark . http_build_query($mixed_data, '', '&'); } } return $url . $query_string; } public static function buildPostData($data, $content_type) { $jsonPattern = '/^(?:application|text)\/(?:[a-z]+(?:[\.-][0-9a-z]+){0,}[\+\.]|x-)?json(?:-[a-z]+)?/i'; $binary_data = false; // Return JSON-encoded string when the request's content-type is JSON and the data is serializable. if (isset($content_type) && preg_match($jsonPattern, $content_type) && ( is_array($data) || ( is_object($data) && interface_exists('JsonSerializable', false) && $data instanceof JsonSerializable ) )) { $data = \Curl\Encoder::encodeJson($data); } elseif (is_array($data)) { // Manually build a single-dimensional array from a multi-dimensional array as using curl_setopt($ch, // CURLOPT_POSTFIELDS, $data) doesn't correctly handle multi-dimensional arrays when files are // referenced. if (ArrayUtil::is_array_multidim($data)) { $data = ArrayUtil::array_flatten_multidim($data); } // Modify array values to ensure any referenced files are properly handled depending on the support of // the @filename API or CURLFile usage. This also fixes the warning "curl_setopt(): The usage of the // @filename API for file uploading is deprecated. Please use the CURLFile class instead". Ignore // non-file values prefixed with the @ character. foreach ($data as $key => $value) { if (is_string($value) && strpos($value, '@') === 0 && is_file(substr($value, 1))) { $binary_data = true; if (class_exists('CURLFile')) { $data[$key] = new CURLFile(substr($value, 1)); } } elseif ($value instanceof CURLFile) { $binary_data = true; } } } if (!$binary_data && (is_array($data) || is_object($data)) && ( !isset($content_type) || !preg_match('/^multipart\/form-data/', $content_type) )) { $data = http_build_query($data, '', '&'); } return $data; }}
测试结果:
划线
评论
复制
发布于: 2020 年 07 月 23 日阅读数: 45
刘卓
关注
还未添加个人签名 2018.04.26 加入
还未添加个人简介
评论