簡體   English   中英

使用Flask和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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM