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
請聽下回分解。
