Flask是Python中有名的輕量級同步Web框架,但是在實際的開發中,可能會遇到需要長時間處理的任務,此時就需要使用異步的方式來實現,讓長時間任務在后台運行,先將本次請求的相應狀態返回給前端,不讓前端界面卡頓。
在碎遮掃描系統的編寫中,當對目標進行全方位掃描時,掃描這個動作是需要長時間處理的。因為現在還沒有加快每個部分的掃描速度,所以想要將一個目標掃描完大概需要五到十分鍾的時間,所以不可能讓用戶一直等待這么長時間的頁面刷新,需要將任務放在后台執行,先給用戶返回正常的界面。
本文介紹Python原生的方式,即多線程或者多進程來進行耗時任務的執行,實現后端的異步處理。這樣也很好理解,直接暴力開啟一個新的線程/進程來進行耗時任務的執行,主線程/進程用來返回正常前端界面給用戶。
通過多線程來實現
import time from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor() #executor = ThreadPoolExecutor(10)里面的數字是線程池所能同時進行的最大數量 def run(): time.sleep(10) print("耗時任務執行結束") @app.route('/test') def test(): # 交給線程去處理耗時任務 executor.submit(run) return "cheer!"
通過多進程來實現:
import time from concurrent.futures import ProcessPoolExecutor executor = ProcessPoolExecutor() #不限制數量的話最大進程數即為電腦CPU的核數 @app.route('/test_console', methods=['GET', 'POST']) @login_required def console(): bugbit, bugtype = core.GetBit() counts = core.GetCounts() ports = core.GetPort() services = core.GetServices() target = core.GetTargetCount() try: lastscantime = BaseInfo.query.order_by(BaseInfo.id.desc()).first().date except: lastscantime = "暫無掃描" pass if request.method == 'GET': return render_template('console.html', bugbit=bugbit, bugtype=bugtype, counts=counts, lastscantime=lastscantime, ports=ports, services=services, target=target) else: urls = request.form.get('urls') urls = urls.split() print(urls) for url in urls: redispool.hincrby('targetscan', 'waitcount', 1) executor.submit(SZheConsole, urls) target = core.GetTargetCount() return render_template('console.html', bugbit=bugbit, bugtype=bugtype, counts=counts, lastscantime=lastscantime,ports=ports, services=services, target=target)
這里是碎遮掃描系統目前后端異步的多進程實現,之前時間匆忙所以實現的很簡陋哈哈哈,今天准備棄掉原生的后端異步實現了,重構一下掃描系統的后端異步。
其中
executor.submit(SZheConsole, urls)
就是使用SZheConsole函數對輸入的掃描目標進行全方位目標檢測,在這里開啟了一個新的進程執行掃描,接着就返回了前端界面,讓用戶能夠正常看到界面。
return render_template('console.html', bugbit=bugbit, bugtype=bugtype, counts=counts, lastscantime=lastscantime, ports=ports, services=services, target=target)
雖然這樣的原生實現異步處理很簡單快捷,但是不足的地方在掃描系統的使用過程中已經有很多師傅提出來了:沒有掃描的進度條顯示,不能對掃描任務進行暫停,如果有個地方卡死了,就只能一直卡在那里,而不能進行丟棄等等,所以需要使用已存在的異步框架來優化異步處理:D
請聽下回分解。