架构师训练营第 7 周课后练习
发布于: 2020 年 12 月 06 日
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
并发数比较低时,系统资源比较充足,随着并发数的增加,响应时间可以近似恒定,TPS近似线性增长;当并发数超过某个点后,资源请求可能会排队等待,响应时间会变长,TPS增长开始变缓;当并发数继续增加达到系统最大负载点后,某些系统资源可能已经耗尽,响应时间会变得非常长,TPS开始急剧下降,直到系统崩溃
用你熟悉的编程语言写一个 Web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
namespace Geektime.LoadTest{ public class LoadTestOption { public int RequestCount { get; set; } public int ConcurrentCount { get; set; } public string TargetUrl { get; set; } }}
】using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.Net;using System.Threading;using System.Threading.Tasks;namespace Geektime.LoadTest{ class LoadTestEngine : BackgroundService { private readonly LoadTestOption option; private readonly ILogger logger; private readonly IHostApplicationLifetime lifetime; public LoadTestEngine( LoadTestOption option, ILogger<LoadTestEngine> logger, IHostApplicationLifetime lifetime ) { this.option = option; this.logger = logger; this.lifetime = lifetime; } protected async override Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Delay(1000); var tasks = new List<Task>(); var globalTotal = 0; var globalTimings = new ConcurrentBag<double>(); for (var i = 0; i < this.option.ConcurrentCount; i++) { var task = Task.Factory.StartNew((state) => { var threadId = Thread.CurrentThread.ManagedThreadId; this.logger.LogInformation($"{threadId}: task start"); var localTotal = 0; while (true) { Interlocked.Increment(ref globalTotal); if (globalTotal > this.option.RequestCount) break; ++localTotal; DateTime startTime = DateTime.Now; var request = WebRequest.Create(this.option.TargetUrl); request.GetResponse(); globalTimings.Add((DateTime.Now - startTime).TotalMilliseconds); } this.logger.LogInformation($"{threadId}: task end with {localTotal} requests"); }, null, TaskCreationOptions.LongRunning); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); try { var average = globalTimings.Average(); var percentile = GetPercentile(globalTimings, 0.95); this.logger.LogInformation($"Avg: {average : 0.00}ms"); this.logger.LogInformation($"95th: {percentile : 0.00}ms"); } catch (Exception ex) { Console.WriteLine(ex.Message); } this.lifetime.StopApplication(); } protected static double GetPercentile(IEnumerable<double> seq, double percentile) { var elements = seq.ToArray(); Array.Sort(elements); double realIndex = percentile * (elements.Length - 1); int index = (int)realIndex; double frac = realIndex - index; if (index + 1 < elements.Length) return elements[index] * (1 - frac) + elements[index + 1] * frac; else return elements[index]; } }}
15: task start 9: task start 10: task start 7: task start 13: task start 12: task start 14: task start 16: task start 11: task start 8: task start 15: task end with 10 requests 11: task end with 9 requests 14: task end with 9 requests 7: task end with 11 requests 9: task end with 11 requests 10: task end with 10 requests 16: task end with 9 requests 12: task end with 10 requests 8: task end with 10 requests 13: task end with 11 requests Avg: 25.91ms 95th: 144.47ms
划线
评论
复制
发布于: 2020 年 12 月 06 日阅读数: 28
菜青虫
关注
还未添加个人签名 2017.11.20 加入
还未添加个人简介
评论