asyncio與gevent並發性能測試


asyncio與gevent並發性能測試

在對網站進行掃描或者暴破時需要對網站進行高並發操作,然而requests+concurrent多線程性能上不太理想,了解到python用得比較多的並發庫有asynciogevent,於是就有了如下測試。

0x00 協程

asynciogevent都是基於攜程來進行並發操作的。協程也被稱為微線程。
協程只是在單一的線程里進行切換不同的協程,因此無法使用多CPU能力,對於CPU密集型程序還是使用多進程比較好。
協程相比較進程和線程來說占用的內容更少,同樣的線程切換更多的是靠操作系統來控制,而協程的執行則由我們自己控制。
並發原理:當其中一個協程遇到io等待時,將會切換到另一個協程繼續運行。

0x01 grequests

grequests是對requestsgevent庫的封裝
測試代碼:

#!/usr/bin/python3.7 import grequests import time if __name__ == '__main__': start = time.time() greenlets = [] for _ in range(10): greenlets.append(grequests.get("http://150.xx.xx.xx")) rets = grequests.map(greenlets) for ret in rets: print(ret) end = time.time() print("grequests visit_async tasks %.2f seconds" % (end - start)) 

grequests.map()參數說明:
def grequests.map(requests, stream=False, size=None, exception_handler=None, gtimeout=None)

參數 說明 備注
size 協程的並發度(相當於線程數) 當一個協程在IO等待時,會將CPU交給其他協程
exception_handler 異常處理函數 用於處理單個請求出現異常的函數
gtimeout 設置所有請求的超時時間  

grequests的底層是request,所以它也支持回調函數:

def print_url(r, *args, **kwargs): print(r.url) res = grequests.get(url, callback=print_url) 

 

 

測試結果:

 
grequsts並發性能測試

0x02 asyncio + uvloop

由於gevent的猴子補丁的緣故,requests可以和gevent結合使用,但是在不清楚內部實現的情況下,requests庫經常比較容易出現Failed to establish a new connection:的情況,在使用grequests庫之后該情況得到解決。
uvloop是用Cython寫的,目前不支持windows,它基於libuv.uvloop使得asyncio更快,基於性能的測試接近於go。
可以通過兩種方式來使用uvloop:

import uvloop import asyncio #1. 通過設置策略 asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) #2. 直接創建一個新的event_loop asyncio.set_event_loop(uvloop.new_event_loop()) 

由於asycnio采用異步操作,它在使用的過程中所有的模塊也都得是異步的,所以在進行http請求時也需要異步,即aiohttp
測試代碼:

#!/usr/bin/python3.7 import asyncio import aiohttp import uvloop import time async def access_url(url): async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: async with session.get(url) as response: status_code = response.status print(status_code) async def visit_async(): start = time.time() tasks = [] for _ in range(10): tasks.append(access_url("http://150.xx.xx.xx")) await asyncio.gather(*tasks) end = time.time() print("asyncio visit_async tasks %.2f seconds" % (end - start)) if __name__ == '__main__': loop = asyncio.get_event_loop() future = asyncio.ensure_future(visit_async()) asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) loop.run_until_complete(future) 

 

 

測試結果:

 
asyncio 並發性能測試

0x03 優缺點

asyncio由於是異步操作,且代碼庫生態不夠完善,部分異步代碼庫存在問題可能查不到,且編寫代碼時行數較多,影響閱讀,而且代庫函數全部重構,上手有難度,但是並發執行的速度較快,對於暴破、端口掃描等比較適用。
gevent采用了requests模塊,在使用了猴子補丁后對於掃描網站路徑等可以有效即時針對掃描結果進行深層掃描。

請求內容:

 

 
請求內容

參考:


 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM