在工做中,要對一個接口進行壓測,我當時就想經過python本身編寫一個壓力發生器。python
經過循環向服務端發送請求,代碼以下:api
#採用單步循環的方式循環測試
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))服務器
測試結果以下:session
|
單線程多線程 |
1併發 |
開始時間: 1536545804.5258229 |
2異步 |
開始時間: 1536546027.6947124 |
3高併發 |
開始時間: 1536546205.2600951 |
4 |
開始時間: 1536546368.2361982 |
5 |
開始時間: 1536546640.4913867 |
運行時間很長,對程序進行了分析,由於循環是單線程而且是同步的,發送請求後,必須等待收到響應,纔會發送下一個請求,效率很低,而且循環對壓力機的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 |
開始時間: 1536546926.9662883 |
2 |
開始時間: 1536546027.6947124 |
開始時間: 1536546962.368912 |
3 |
開始時間: 1536546205.2600951 |
開始時間: 1536546990.911677 |
4 |
開始時間: 1536546368.2361982 |
開始時間: 1536547021.2030604 |
5 |
開始時間: 1536546640.4913867 |
開始時間: 1536547046.3298163 |
測試效率有很大提升,但也存在問題,當啓動線程較多時,壓力機資源消耗大,在同一個線程內部,仍是同步進行,效率較低。
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 |
開始時間: 1536546926.9662883 |
開始時間: 1536565502.732898 |
2 |
開始時間: 1536546027.6947124 |
開始時間: 1536546962.368912 |
開始時間: 1536565502.732898 |
3 |
開始時間: 1536546205.2600951 |
開始時間: 1536546990.911677 |
開始時間: 1536565502.732898 |
4 |
開始時間: 1536546368.2361982 |
開始時間: 1536547021.2030604 |
開始時間: 1536565502.732898 |
5 |
開始時間: 1536546640.4913867 |
開始時間: 1536547046.3298163 |
開始時間: 1536565502.732898 |
性能大大提升,但還有一個須要優化的地方,tasks採用的是list,若是數量多了,會佔用大量內存,下步進行優化。