# -*- coding: utf-8 -*-
'''
@author: Carry
@file: grequests_test.py
@time: 2020/9/3 9:53
@desc: 接口并发测试
'''
import grequests
import time
import grequests_throttle as gt
import json
import requests
from carry_zone.tools import call_time
url = "https://www.cnblogs.com/superhin/p/11583560.html"
url = 'http://172.32.147.45:5000/test'
json_str = '{"uuid":"c3cf9431-0132-46d7-8e7a-09f530a99571","fimage":[]}'
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
# "Accept": "ext/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
'Content-Type': 'application/json'
}
def get_exception(Request, Exception):
'''
异常处理
:param Request:
:param Exception:
:return:
'''
print(Exception)
@call_time()
def use_grequests(num, url=None):
'''
普通并发
:param num: 总请求次数
:param url:
:return:
'''
urls = [url for i in range(num)]
task = (grequests.post(u, data=json_str, headers=headers) for u in urls)
resp = grequests.map(task, exception_handler=get_exception)
return resp
@call_time()
def use_grequests_with_size(num, url=None):
'''
指定每次请求的数目
:param num: 总共请求次数
:param url:
:return:
'''
urls = [url for i in range(num)]
task = (grequests.post(u, data=json_str, headers=headers) for u in urls)
# 指定每次请求的数目。如果没有,则不会发生节流。
resp = grequests.map(task, size=40, exception_handler=get_exception)
return resp
@call_time()
def use_grequests_throttle(num, url=None):
'''
带限制的请求,每秒并发rate个
:param num: 总共请求次数
:param url:
:return:
'''
urls = [url for i in range(num)]
task = (gt.post(u, data=json_str, headers=headers) for u in urls)
# 指定每秒并发的数量。如果没有,则不会发生节流。
resp = gt.map(task, rate=20, exception_handler=get_exception)
return resp
@call_time()
def use_requests(num, url=None):
'''
正常requests请求,阻塞
:param num:
:param url:
:return:
'''
urls = [url for i in range(num)]
index = 0
while urls:
url = urls.pop(0)
resp = requests.get(url=url, headers=headers)
index += 1
if index % 10 == 0:
print('目前是第{}个请求'.format(index))
def main(num):
# use_requests(num, url)
# 请求100次,CPU占用43%,use_grequests_with_size call_time:9.6287841796875,avg:5.14814134
# res = use_grequests(num, url)
# 请求100次,size= 5,CPU占用43%,use_grequests_with_size call_time:8.950897693634033,avg:0.43644715
# 请求100次,size=10,CPU占用43%,use_grequests_with_size call_time:8.93743085861206, avg:0.8518633799999997
# 请求100次,size=20,CPU占用43%,use_grequests_with_size call_time:9.013700246810913,avg:1.6296260900000004
# 请求100次,size=40,CPU占用43%,use_grequests_with_size call_time:9.170267343521118,avg:2.965993030000001 (翻倍增长)
# res = use_grequests_with_size(num, url)
# 每秒并发测试
res = use_grequests_throttle(num, url)
avg = 0
for res in res:
avg += res.elapsed.total_seconds()
print("call time:{},status code:{}".format(res.elapsed.total_seconds(), res.status_code))
print('avg:{}'.format(avg / num))
if __name__ == '__main__':
main(100)
'''
每秒并发测试处理结果
程序处理单个请求时长约0.18s
locust
RUNNING 3 users,请求了1034次,每个请求平均响应时长 0.255s 此时CPU占用45%
RUNNING 5 users,请求了1479次,每个请求平均响应时长 0.436s
RUNNING 10 users,请求了1028次,每个请求平均响应时长 0.861s
RUNNING 20 users,请求了1037次,每个请求平均响应时长 1.706s
RUNNING 25 users,请求了3722次,每个请求平均响应时长 2.111s 此时CPU占用45%
grequests
每秒请求 3 个,请求了1000次,每个请求平均响应时长 0.7382s 此时CPU占用11%
每秒请求 5 个,请求了1000次,每个请求平均响应时长 0.7273s
每秒请求 10 个,请求了1000次,每个请求平均响应时长 0.8283s
每秒请求 20 个,请求了1000次,每个请求平均响应时长 1.7453s
每秒请求 25 个,请求了3722次,每个请求平均响应时长 2.1978s 此时CPU占用45%
结论:当每秒并发数大于程序每秒处理数时,locust界面压测和grequests请求测试方式基本相当。
但是当程序每秒处理数大于grequests的每秒请求数时,怀疑grequests强制等待完一秒,再发送下一批并发数?
(比如5个并发程序0.6秒就处理完了,但是继续等待了0.4秒后才返回,导致整个响应时长变慢,个人猜想。)
所以locust更符合实际应用场合。
'''