使用python脚本对http接口进行压测
原理
使用python通过requests对http接口进行压测。原理是启动多线程+线程内循环调用http接口,达到压测目的。
注意
其中login()方法目的是登录后获取token等身份验证信息,以便在testinterface()中使用。
若压测无需身份验证的接口,可屏蔽obj.login(),以requests.post()的方式直接调用http接口即可。
常见错误
另外,可通过在浏览器地址栏输入 about:version 的方式来获取 User-Agent(用户代理),以更新脚本中的headers.User-Agent,避免出现”RemoteDisconnected: Remote end closed connection without response“等问题。
代码:
import requests,time,json,threading
class Presstest(object):
headers = {
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36,
Content-Type: application/json;,
}
def __init__(self,login_url,biz_url,account,password,data):
self.login_url = login_url
self.biz_url = biz_url
self.account = account
self.password = password
self.data = data
self.session = requests.Session()
self.session.headers = self.headers
#登录
def login(self):
登陆获取session
data = data = {
t: int(time.time() * 1000), account: self.account, password: self.password}
res = self.session.post(self.login_url,data=json.dumps(data))
#判断登录接口响应码
if res.json().get(code) == 200:
print(threading.current_thread().name, 登录成功
)
else:
print(threading.current_thread().name, 登录失败,原因:, res.json(),
)
#获取token并设置请求头
XToken = res.json().get(data).get(xxx_token)
self.session.headers[token] = XToken
#调用目标方法
def testinterface(self):
压测接口
global ERROR_NUM
try:
t1 = time.time()
#调用post接口
html = self.session.post(self.biz_url, json.dumps(self.data))
#html = requests.post(self.biz_url, self.data, headers=self.headers)
t2 = time.time()
if html.json().get(code) == 200:
print(threading.current_thread().name, 请求成功,耗时:, t2-t1,
)
#打印响应信息
#print(threading.current_thread(), 请求成功,耗时:, t2-t1, 响应:, html.json(),
)
else:
print(threading.current_thread().name, 请求失败,原因:, html.json(),
)
ERROR_NUM += 1
except Exception as e:
print(e)
ERROR_NUM += 1
#单线程内循环调用目标方法
def testonework(self):
一次并发处理单个任务
i = 0
while i < ONE_WORKER_NUM:
i += 1
self.testinterface()
time.sleep(LOOP_SLEEP)
#启动多个线程
def run(self):
使用多线程进程并发测试
t1 = time.time()
Threads = []
for i in range(THREAD_NUM):
t = threading.Thread(target=self.testonework, name="T" + str(i))
#t.setDaemon(True)过时
t.daemon=True
Threads.append(t)
for t in Threads:
t.start()
for t in Threads:
t.join()
t2 = time.time()
print("===============压测结果===================")
print("URL:", self.biz_url)
print("任务数量:", THREAD_NUM, "*", ONE_WORKER_NUM, "=", THREAD_NUM * ONE_WORKER_NUM)
print("总耗时(秒):", t2 - t1)
print("每次请求耗时(秒):", (t2 - t1) / (THREAD_NUM * ONE_WORKER_NUM))
print("每秒承载请求数:", (THREAD_NUM * ONE_WORKER_NUM) / (t2 - t1))
print("错误数量:", ERROR_NUM)
if __name__ == __main__:
#登录url
login_url = https://xxx.com/api/xxx/login
#登录用户名
account="xxx"
#登录密码
password="xxx"
#压测url
biz_url = https://xxx.com/api/xxx/xxx
#请求参数 java接口需@RequestBody接收参数,否则无法解析
data={
"id": 2}
THREAD_NUM = 1 # 并发线程总数
ONE_WORKER_NUM = 1 # 每个线程的循环次数
LOOP_SLEEP = 0 # 每次请求时间间隔(秒)
ERROR_NUM = 0 # 出错数
obj = Presstest(login_url=login_url,biz_url=biz_url,account=account,password=password,data=data)
obj.login()
obj.run()
#运行后不自动关闭窗口
input(Press Enter to exit...)
