python异步高并发_通过python异步通讯方式构建高并发压力测试工具

背景说明

在工作中,要对一个接口进行压测,我当时就想通过python自己编写一个压力发生器。

初步方案(单线程循环发送)

通过循环向服务端发送请求,代码如下:

#采用单步循环的方式循环测试

import requests,time

def run(runnum):

url = "https://api-test.peanut.ai/wechatGrant/load/test1?openId=RP0ulQ4pHDTBWt77ILCs02QGU&bsscode=8167871547864571"

for i in range(runnum):

str_res = requests.get(url)

if __name__ == "__main__":

start_time = time.time()

run(100)

end_time = time.time()

#print("循环次数:",str(counut))

print("开始时间:",str(start_time))

print("结束时间:",str(end_time))

print("运行时间:",str(end_time - start_time))

测试结果如下:

单线程

1

开始时间: 1536545804.5258229

结束时间: 1536545879.1070435

运行时间: 74.58122062683105

2

开始时间: 1536546027.6947124

结束时间: 1536546100.3893104

运行时间: 72.69459795951843

3

开始时间: 1536546205.2600951

结束时间: 1536546270.549498

运行时间: 65.28940296173096

4

开始时间: 1536546368.2361982

结束时间: 1536546435.7475684

运行时间: 67.51137018203735

5

开始时间: 1536546640.4913867

结束时间: 1536546712.5064435

运行时间: 72.015056848526

运行时间很长,对程序进行了分析,因为循环是单线程并且是同步的,发送请求后,必须等待收到响应,才会发送下一个请求,效率很低,并且循环对压力机的CPU资源消耗较大。

多线程方案

考虑通过多线程提高测试效率,代码如下:

import threading

import requests

import time

url = "https://api-test.peanut.ai/wechatGrant/load/test1?openId=RP0ulQ4pHDTBWt77ILCs02QGU&bsscode=8167871547864571"

def run_thread(snum,enum):

for i in range(snum,enum):

#s = requests.session()

#关闭长连接

headers = {'Connection': 'close'}

str_res = requests.get(url,headers=headers)

#从发送请求到收到响应消耗的时间,单位微妙。

etime = str_res.elapsed.microseconds/1000000

threads = []

for i in range(0,10):

#循环生成线程

t = threading.Thread(target=run_thread, args=(0,10))

threads.append(t)

if __name__ == "__main__":

start_time = time.time()

for dd in range(0,10):

#启动线程

threads[dd].start()

for dd in range(0,10):

threads[dd].join()

end_time = time.time()

print("开始时间:",str(start_time))

print("结束时间:",str(end_time))

print("运行时间:",str(end_time - start_time))

测试结果如下:

单线程

多线程(10)

1

开始时间: 1536545804.5258229

结束时间: 1536545879.1070435

运行时间: 74.58122062683105

开始时间: 1536546926.9662883

结束时间: 1536546935.9247773

运行时间: 8.958488941192627

2

开始时间: 1536546027.6947124

结束时间: 1536546100.3893104

运行时间: 72.69459795951843

开始时间: 1536546962.368912

结束时间: 1536546970.9876196

运行时间: 8.618707656860352

3

开始时间: 1536546205.2600951

结束时间: 1536546270.549498

运行时间: 65.28940296173096

开始时间: 1536546990.911677

结束时间: 1536547001.0316806

运行时间: 10.120003700256348

4

开始时间: 1536546368.2361982

结束时间: 1536546435.7475684

运行时间: 67.51137018203735

开始时间: 1536547021.2030604

结束时间: 1536547030.7051418

运行时间: 9.502081394195557

5

开始时间: 1536546640.4913867

结束时间: 1536546712.5064435

运行时间: 72.015056848526

开始时间: 1536547046.3298163

结束时间: 1536547054.6956365

运行时间: 8.365820169448853

测试效率有很大提高,但也存在问题,当启动线程较多时,压力机资源消耗大,在同一个线程内部,还是同步进行,效率较低。

异步通讯方案

asyncio可以实现单线程并发IO操作。如果仅用在客户端,发挥的威力不大。如果把asyncio用在服务器端,例如Web服务器,由于HTTP连接就是IO操作,因此可以用单线程+coroutine实现多用户的高并发支持。

#采用异步通讯的方式发压

import requests,time

import asyncio

from aiohttp import ClientSession

import aiohttp

url = "https://api-test.peanut.ai/wechatGrant/load/test1?openId=RP0ulQ4pHDTBWt77ILCs02QGU&bsscode=8167871547864571"

tasks = []

async def run():

async with ClientSession() as session:

async with session.get(url) as response:

response = await response.read()

#print(response)

if __name__ == "__main__":

loop = asyncio.get_event_loop()

start_time = time.time()

for i in range(100):

tasks.append(run())

end_time = time.time()

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

#print("循环次数:",str(counut))

print("开始时间:",str(start_time))

print("结束时间:",str(end_time))

print("运行时间:",str(end_time - start_time))

测试结果:

单线程

多线程(10)

异步

1

开始时间: 1536545804.5258229

结束时间: 1536545879.1070435

运行时间: 74.58122062683105

开始时间: 1536546926.9662883

结束时间: 1536546935.9247773

运行时间: 8.958488941192627

开始时间: 1536565502.732898

结束时间: 1536565502.732898

运行时间: 0.0

2

开始时间: 1536546027.6947124

结束时间: 1536546100.3893104

运行时间: 72.69459795951843

开始时间: 1536546962.368912

结束时间: 1536546970.9876196

运行时间: 8.618707656860352

开始时间: 1536565502.732898

结束时间: 1536565502.732898

运行时间: 0.0

3

开始时间: 1536546205.2600951

结束时间: 1536546270.549498

运行时间: 65.28940296173096

开始时间: 1536546990.911677

结束时间: 1536547001.0316806

运行时间: 10.120003700256348

开始时间: 1536565502.732898

结束时间: 1536565502.732898

运行时间: 0.0

4

开始时间: 1536546368.2361982

结束时间: 1536546435.7475684

运行时间: 67.51137018203735

开始时间: 1536547021.2030604

结束时间: 1536547030.7051418

运行时间: 9.502081394195557

开始时间: 1536565502.732898

结束时间: 1536565502.732898

运行时间: 0.0

5

开始时间: 1536546640.4913867

结束时间: 1536546712.5064435

运行时间: 72.015056848526

开始时间: 1536547046.3298163

结束时间: 1536547054.6956365

运行时间: 8.365820169448853

开始时间: 1536565502.732898

结束时间: 1536565502.732898

运行时间: 0.0

性能大大提高,但还有一个需要优化的地方,tasks采用的是list,如果数量多了,会占用大量内存,下步进行优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值