使用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, '登录成功\n')
    else:
      print(threading.current_thread().name, '登录失败,原因:', res.json(), '\n')
    #获取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, '\n')
        #打印响应信息
        #print(threading.current_thread(), '请求成功,耗时:', t2-t1, '响应:', html.json(), '\n')
      else:
        print(threading.current_thread().name, '请求失败,原因:', html.json(), '\n')
        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...')    
     

你可能感兴趣的:(python,http,开发语言,java,压力测试)