python 并发请求(设定吞吐量)

需求是,每秒发起请求(异步)

前提,压测接口,response time 为3-5秒

复制代码
 1 from flask import Flask
 2 import random
 3 import time
 4 
 5 app = Flask(__name__)
 6 
 7 
 8 @app.route('/')
 9 def hello_world():
10     return 'Hello, World!'
11 
12 
13 @app.route('/time', methods=['POST', 'GET'])
14 def atime():
15     a = random.randint(3, 5)
16     time.sleep(a)
17     s = 'time ---->' + str(a)
18     if a == 5:
19         s = 1 / 0
20     return s
21 
22 
23 if __name__ == '__main__':
24     app.run()
复制代码

请求地址:http://127.0.0.1:5000/time

 

1.尝试使用jmeter压测,发现只能做到同步(获得结果后再发起请求)

 2.python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
from threading import Thread
import requests
# import matplotlib.pyplot as plt
import datetime
import time
import numpy as np
import json
 
 
class ThreadTest(Thread):
    def __init__(self, func, args=()):
        '''
      :param func: 被测试的函数
      :param args: 被测试的函数的返回值
      '''
        super(ThreadTest, self).__init__()
        self.func = func
        self.args = args
 
    def run(self) -> None:
        self.result = self.func(*self.args)
 
    def getResult(self):
        try:
            return self.result
        except BaseException as e:
            return e.args[0]
 
 
def baiDu(url, code, seconds):
    '''
   :param code: 状态码
   :param seconds: 请求响应时间
   :return:
   '''
    r = requests.get(url=url)
    code = r.status_code
    seconds = r.elapsed.total_seconds()
    return code, seconds
 
 
def calculationTime(startTime, endTime):
    '''计算两个时间之差,单位是秒'''
    return (endTime - startTime).seconds + (endTime - startTime).days*24*60*60
 
 
def getResult(seconds):
    '''获取服务端的响应时间信息'''
    data = {
        'Max': sorted(seconds)[-1],
        'Min': sorted(seconds)[0],
        'Median': np.median(seconds),
        '99%Line': np.percentile(seconds, 99),
        '95%Line': np.percentile(seconds, 95),
        '90%Line': np.percentile(seconds, 90)
    }
    return data
 
 
def highConcurrent(url, count, countPerS):
    '''
   对服务端发送高并发的请求
   :param cout: 并发数
   :return:
   '''
    global throughput
    startTime = datetime.datetime.now()
    sum = 0
    list_count = list()
    tasks = list()
    results = list()
    # 失败的信息
    fails = []
    # 成功任务数
    success = []
    codes = list()
    seconds = list()
 
    for i in range(int(count)):
        # DispatchIDS = ['CMA01', 'DAA03', 'MPL0A', 'DCA01', 'CUE0A', 'DKA03', 'DRA51', 'MAA01', 'RAA52', 'WHJ02']
        # import random
        # DispatchID = random.choice(DispatchIDS)
        # DispatchID = DispatchIDS[i % 10]
        # url = 'http://10.50.45.240:8080/rtd/92?DispatchID=' + DispatchID
        import random
        alamRandint = random.randint(3,5)
        url = "http://127.0.0.1:5000/time/"+ str(alamRandint)
        t = ThreadTest(baiDu, args=(url, i, i))
        tasks.append(t)
        t.start()
        print(datetime.datetime.now())
        time.sleep(1 / countPerS)
 
 
 
    for t in tasks:
        t.join()
        if t.getResult()[0] != 200:
            fails.append(t.getResult())
        results.append(t.getResult())
 
    for item in results:
        codes.append(item[0])
        seconds.append(item[1])
    for i in range(len(codes)):
        list_count.append(i)
 
    # 生成可视化的趋势图
    # fig, ax = plt.subplots()
    # ax.plot(list_count, seconds)
    # ax.set(xlabel='number of times', ylabel='Request time-consuming',
    #        title='olap continuous request response time (seconds)')
    # ax.grid()
    # fig.savefig('olap.png')
    # plt.show()
    # print("seconds ==",seconds)
    # print("list_count ==", list_count)
    # print("fails ==", fails) #[]
    # print("success ==",success) #[]
    # print("results ==", results)
 
    for i in seconds:
        # print('i', i)
        # print('type(i)', type(i))
        if type(i) == type(1.0):
            sum += i
        else:
            sum += 0
            # len(list_count)-len(fails)
    # print('sum', sum)
    # print("len(list_count)", len(list_count))
    rate = sum / len(list_count)
    endTime = datetime.datetime.now()
    # print('\n总共持续时间:\n',endTime-startTime)
    totalTime = calculationTime(startTime=startTime, endTime=endTime)
    # print('totalTime', totalTime)
    if totalTime < 1:
        totalTime = 1
    # 吞吐量的计算
    try:
        print("float(len(list_count) ", float(len(list_count)))
        print("totalTime", totalTime)
        throughput = float(len(list_count) / totalTime)
    except Exception as e:
        print(e.args[0])
    getResult(seconds=seconds)
    errorRate = 0
    if len(fails) == 0:
        errorRate = 0.00
    else:
        errorRate = len(fails) / len(tasks) * 100
    throughput = str(throughput) + '/S'
    timeData = getResult(seconds=seconds)
    dict1 = {
        '吞吐量(tps)': throughput,
        '平均响应时间(s)': rate,
        '响应时间(s)': timeData,
        '请求总数': len(list_count),
        '错误数': len(fails),
        '错误率(%)': errorRate,
        '执行时间(s)': totalTime
    }
    return json.dumps(dict1, indent=True, ensure_ascii=False)
 
 
if __name__ == '__main__':
    DispatchIDS = ['CMA01', 'DAA03', 'MPL0A', 'DCA01', 'CUE0A', 'DKA03', 'DRA51', 'MAA01', 'RAA52', 'WHJ02']
    url = 'http://10.50.45.240:8080/rtd/92?DispatchID='
 
    days = 1
    hours = 1
    minutes = 1
    seconds = 10
    countPerS = 1  # 每秒请求数量<br>
 
    counts = days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds
    counts = counts * countPerS
    # print(counts)
    print(highConcurrent(url=url, count=counts, countPerS=countPerS))
 
'''
2023-07-11 11:30:54.941397
2023-07-11 11:30:55.455986
....
2023-07-11 11:31:24.244365
2023-07-11 11:31:24.750616
{
 "吞吐量(tps)": "1.8181818181818181/S",
 "平均响应时间(s)": 3.963214083333334,
 "响应时间(s)": {
  "Max": 5.02367,
  "Min": 3.005881,
  "Median": 4.009576,
  "99%Line": 5.01937067,
  "95%Line": 5.013791149999999,
  "90%Line": 5.0105454
 },
 "请求总数": 60,
 "错误数": 0,
 "错误率(%)": 0.0,
 "执行时间(s)": 33
}
 
nohup python my.py >> my.log 2>&1 &
# 等价于下面两行的内容
nohup python my.py 1>> my.log &
nohup python my.py 2>> my.log &
'''

  

  

返回结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2023-07-08 16:24:48.524257
2023-07-08 16:24:49.027055
2023-07-08 16:24:49.539939
.......
2023-07-08 17:25:57.709663
2023-07-08 17:25:58.225109
 
{
 "吞吐量(tps)": "1.9599782194391506/S",
 "平均响应时间(s)": 4.006165397416303,
 "响应时间(s)": {
  "Max": 5.036263,
  "Min": 3.002034,
  "Median": 4.009866,
  "99%Line": 5.01809934,
  "95%Line": 5.0155911,
  "90%Line": 5.0130394
 },
 "请求总数": 7199,
 "错误数": 2368,
 "错误率(%)": 32.893457424642314,
 "执行时间(s)": 3673
}
 
Process finished with exit code 0

  运行方式(后台运行,实时查看数据)

1
2
3
nohup python -u alamThreadRequests.py >> alam0712.log 2>&1 &
 
tail -f alam0712.log

  

posted @   AlamZ  阅读(418)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示