2016-01-11 39 views
8

Tôi cố gắng thiết lập một ứng dụng Flask tối thiểu sử dụng eventlet để trả lời các yêu cầu đồng thời ngay lập tức thay vì chặn và trả lời một yêu cầu sau khi yêu cầu khác (như máy chủ web Flask chuẩn).Trả lời các yêu cầu đồng thời với Flask và eventlet

Điều kiện tiên quyết:

pip install Flask 
pip install eventlet 

Từ sự hiểu biết của tôi bằng những gì tôi tìm thấy cho đến nay trên internet, nó sẽ hoạt động như thế này:

# 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) 

Khi chạy tập tin này, sau đó mở http://localhost:5000/longTask trong một WebBrowser và trong khi nó vẫn đang xử lý mở một tab khác với http://localhost:5000/shortTask, tôi hy vọng tab thứ hai sẽ trở lại ngay lập tức trong khi tab đầu tiên vẫn đang tải. Tuy nhiên, tương tự như khi chạy trên máy chủ Werkzeug tiêu chuẩn, tab thứ hai chỉ trả về ngay sau khi tab đầu tiên kết thúc sau 30 giây.

Có gì sai ở đây? Nhân tiện, đây có phải là điều thường được gọi là "máy chủ web sẵn sàng sản xuất" cho Flask, vì chỉ có ít người dùng đồng thời được mong đợi (tối đa là 5 người)?

Nhân tiện, khi tôi sử dụng the Flask-socketio library để chạy máy chủ web, theo tài liệu, tự động chọn sự kiện nếu nó được cài đặt, sau đó nó hoạt động như mong đợi.

Toàn bộ ví dụ với 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) 

Trả lời

11

Khi bạn chạy app.run(debug=True), bạn đang thông báo rõ ràng cho Flask để chạy ứng dụng của bạn trên máy chủ web phát triển, dựa trên Werkzeug. Nó không quan trọng là bạn đã nạp eventlet.

Nếu bạn muốn chạy ứng dụng của bạn trên máy chủ eventlet web, bạn phải bắt đầu một máy chủ web eventlet, mà theo the documentation được bắt đầu như sau:

wsgi.server(eventlet.listen(('', 8000)), your_app) 

này là nhiều hơn hoặc ít hơn những gì socketio.run() làm trong phần mở rộng Flask-SocketIO của tôi, với một chút phức tạp hơn để tùy chọn xử lý SSL. Các dòng mã thực hiện điều này là: https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/init.py#L391-L408. Nếu bạn nhìn xung quanh những dòng này, bạn sẽ thấy rằng có ba phần khởi đầu khác nhau của mã, một cho werkzeug, một cho eventlet và một cho gevent. Tất cả đều khác nhau.

+0

Tuyệt vời! Việc truyền đối tượng ứng dụng Flask cho lệnh 'wsgi.server' không rõ ràng với tôi từ ví dụ trong tài liệu của sự kiện, vì vậy ví dụ dựa trên Flask này rất hữu ích. – Dirk

2
import eventlet 
eventlet.monkey_patch() 

Sẽ không kỳ diệu biến mã của bạn vào một con thú multithread có thể xử lý yêu cầu không đồng bộ (nó vẫn còn khá huyền diệu và tuyệt vời).

Như bạn có thể thấy trong this example, bạn cần khởi chạy máy chủ wsgi sử dụng eventlet wsgi's implementation.

Nếu bạn muốn có giải pháp tiêu chuẩn, hãy xem cách sử dụng nginx và uwsgi để khởi chạy ứng dụng bình. Bạn cũng có thể quan tâm đến dự án Spawning để tận dụng nỗi đau của việc tạo ra một trình xử lý đa luồng wsgi hoàn chỉnh.

Các vấn đề liên quan