接口并发测试

# -*- 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更符合实际应用场合。
'''

猜你喜欢

转载自blog.csdn.net/xkx_07_10/article/details/108385144