写点什么

性能测试, 简单的压测工具

用户头像
garlic
关注
发布于: 2020 年 11 月 06 日
性能测试,简单的压测工具

性能测试



性能测试指标:



  • 并发数:同一时刻处理的请求数.

  • 响应时间:完成某一处理使用的时间.

  • 吞吐量: 一段时间内成功响应的数量.



如果从用户视角对并发数和响应时间两个指标没有非常严格的定义.

业务层面提供的并发用户数,一般也是使用系统用户数,系统设计时要结合用户行为模型才能得到系统实际并发数

另外,可以以通过提前渲染技术,使得用户主观感觉到的响应时间要小于系统实际的响应时间

并发数,响应时间和吞吐量之间关系



三个阶段:





线性增长阶段- Light Load Zone:这一时期, 并发数逐步增大,都在系统处理范围内, 吞吐量线性增长, 响应时间无明显变化

高负载阶段 - Heavy Load Zone:并发数增加,吞吐量稳定,随着用户的增加,用户响应时间逐渐变长.

拐点阶段- Buckle Zone:并发量继续增加, 到达某一个点时, 系统某一模块或组件首先出现异常, 导致整体响应时间变长,吞吐量下降,进入系统拐点.

导致模块或组件异常的原因可能是网络连接或文件打开到达系统上限, 或者cpu,内存耗尽等.



简单的压测工具



python实现简单压测工具

输入参数:URL,请求总次数,并发 数。输出参数:平均响应时间,95%响应时间。



大致思路:

根据参数创建多个线程, 要实现并发,通过Threading.Barrier,并行的线程间等待。实现同时发送请求, 结果存放到Queue中, 使用一个线程进行统计输出。



[root@centosgpt python]# cat stress.py
import argparse
import requests
import threading
from queue import Queue
from queue import Empty


def getarg():
parser = argparse.ArgumentParser(description='benchmarking tool', usage = '%(prog)s [options]')
parser.add_argument( '-n', '--requests', type=int, help='Number of requests to perform' )
parser.add_argument( '-c', '--concurrency', type=int, help='Number of multiple requests to make at a time' )
parser.add_argument( 'url', type=str, help='[https|http][://]hostname[:port]/path' )
args = parser.parse_args()
return args



def dowork(url, b, q, i):
b.wait()
print(f'thread {i} request..')
status, response = getstatus(url)
print(f'thread {i} response..', url, status, response)
if status == 'success':
q.put(response)

def getstatus(url):
try:
r = requests.get(url, timeout=10)
return "success", r.elapsed.total_seconds()
except:
return "error", -1


def total():
cnt = 0
sum = 0.0
list = []
thread_stop = False
while not thread_stop:
try:
response = q.get(True, 5)
q.task_done()
except Empty:
thread_stop = True
break
#print ('get response:')
#print (response)
sum += float(response)
cnt += 1
list.append(response)
list.sort(reverse=True)
value95 = list[round(0.05*len(list))]
average = sum / cnt;
print(f' 95% 响应时间 {round(value95, 2)} second(s)')
print(f' 平均响应时间 {round(average, 2)} second(s)')
return average, value95



def totalrun():
t = threading.Thread(target=total, args=())
t.setDaemon(True)
t.start()
return t


def run(concurrency, url, cnt, q):
b = threading.Barrier(concurrency, timeout=15)
threads = []
for i in range(concurrency):
t = threading.Thread(target=dowork, args=(url,b,q, (cnt)*concurrency+i+1 ))
t.setDaemon(True)
t.start()
threads.append(t)
for t in threads:
t.join()


def stress(concurrency, url, cnt, q):
for i in range(cnt):
run(concurrency, url, i, q)


if __name__ == "__main__":
args = getarg()
q = Queue(args.requests)
print(f'请求总数 {args.requests}')
print(f'并发数 {args.concurrency}')
print(f'URL {args.url}')
stress(args.concurrency, args.url, (int)(args.requests/args.concurrency), q)
t = totalrun()
q.join()
t.join()




# python3 stress.py -n 100 -c 10 https://www.baidu.com



Python 3.6.8 (default, Aug 7 2019, 17:28:10)

pip3 install requests



输出结果:

...
thread 100 request..
thread 94 request..
thread 99 request..
thread 91 request..
thread 97 request..
thread 93 request..
thread 95 request..
thread 92 request..
thread 96 request..
thread 98 request..
thread 97 response.. https://www.baidu.com success 0.173782
thread 93 response.. https://www.baidu.com success 0.175232
thread 100 response.. https://www.baidu.com success 0.179685
thread 92 response.. https://www.baidu.com success 0.180536
thread 96 response.. https://www.baidu.com success 0.179596
thread 99 response.. https://www.baidu.com success 0.187891
thread 91 response.. https://www.baidu.com success 0.185512
thread 98 response.. https://www.baidu.com success 0.356688
thread 94 response.. https://www.baidu.com success 0.382427
thread 95 response.. https://www.baidu.com success 0.366883
95% 响应时间 0.67 second(s)
平均响应时间 0.25 second(s)



参考及引用



架构师训练营作业-李智慧老师相关讲义

茹炳晟(Rú bǐng chéng)-软件测试52讲

Photo by Ave Calvar Martinez from Pexels

https://publib.boulder.ibm.com/httpserv/cookbook/Cookbook_General-Theory.html



用户头像

garlic

关注

还未添加个人签名 2017.11.15 加入

还未添加个人简介

评论

发布
暂无评论
性能测试,简单的压测工具