![](/img/trans.png)
[英]Handle concurrent requests or threading Flask SocketIO with eventlet
[英]Responding to concurrent requests with Flask and eventlet
我嘗試設置一個最小的Flask應用程序,該應用程序使用eventlet立即響應並發請求,而不是阻塞並響應一個請求(如標准的Flask調試Web服務器那樣)。
先決條件:
pip install Flask
pip install eventlet
從我到目前為止在互聯網上發現的東西的理解,它應該像這樣工作:
# activate eventlet
import eventlet
eventlet.monkey_patch()
from flask import Flask
import datetime
from time import sleep
# create a new Flask application
app = Flask(__name__)
# a short running task that returns immediately
@app.route('/shortTask')
def short_running_task():
start = datetime.datetime.now()
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# a long running tasks that returns after 30s
@app.route('/longTask')
def long_running_task():
start = datetime.datetime.now()
sleep(30)
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# run the webserver
if __name__ == '__main__':
app.run(debug=True)
運行此文件時,然后在webbrowser選項卡中打開http://localhost:5000/longTask
,當它仍在處理打開另一個帶有http://localhost:5000/shortTask
的選項卡時,我希望第二個選項卡能夠立即返回第一個標簽仍在加載。 但是,與在標准Werkzeug服務器上運行此類似時,第二個選項卡僅在第一個選項卡在30秒后完成后才返回。
這有什么不對? 那么,對於Flask來說,這通常被稱為“生產就緒的網絡服務器”,假設只有很少的並發用戶(最多5個)?
順便說一句,當我使用Flask-socketio庫運行web服務器時,根據文檔,如果安裝了eventlet,它會自動選擇eventlet,然后按預期工作。
Flask-socketio的完整示例:
# activate eventlet
import eventlet
eventlet.monkey_patch()
from flask import Flask
from flask_socketio import SocketIO
import datetime
from time import sleep
# create a new Flask application
app = Flask(__name__)
# activate Flask-socketio
socketio = SocketIO(app)
# a short running task that returns immediately
@app.route('/shortTask')
def short_running_task():
start = datetime.datetime.now()
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# a long running tasks that returns after 30s
@app.route('/longTask')
def long_running_task():
start = datetime.datetime.now()
sleep(30)
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# run the webserver with socketio
if __name__ == '__main__':
socketio.run(app, debug=True)
當您運行app.run(debug=True)
您明確告訴Flask在開發Web服務器上運行您的應用程序,該服務器基於Werkzeug。 加載eventlet沒關系。
如果要在eventlet Web服務器上運行應用程序,則必須啟動一個eventlet Web服務器,該服務器根據文檔啟動如下:
wsgi.server(eventlet.listen(('', 8000)), your_app)
這或多或少是socketio.run()
在我的Flask-SocketIO擴展中的作用,可選擇處理SSL的復雜程度socketio.run()
。 的代碼,做到這一點的線路有: https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/ 初始化的.py#L391-L408 。 如果你環顧這些行,你會發現有三個不同的啟動代碼塊,一個用於werkzeug,一個用於eventlet,一個用於gevent。 他們都是不同的。
import eventlet
eventlet.monkey_patch()
不會神奇地將你的代碼變成一個可以異步處理請求的多線程野獸(它仍然非常神奇和令人敬畏)。
正如您在此示例中所看到的,您需要使用eventlet wsgi的實現來啟動wsgi
服務器。
如果您需要標准解決方案,請查看如何使用nginx和uwsgi來啟動flask應用程序。 您也可能對Spawning項目感興趣,該項目利用創建完整的多線程wsgi處理程序的痛苦。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.