2015-08-06 21 views
21

Tôi đang viết một ứng dụng trong Flask, hoạt động thực sự tốt ngoại trừ việc WSGI là đồng bộ và chặn. Tôi có một nhiệm vụ cụ thể gọi ra API của bên thứ ba và nhiệm vụ đó có thể mất vài phút để hoàn thành. Tôi muốn thực hiện cuộc gọi đó (nó thực sự là một loạt các cuộc gọi) và để cho nó chạy. trong khi điều khiển được trả về Flask.Thực hiện tác vụ không đồng bộ trong Flask

Quan điểm của tôi trông giống như:

@app.route('/render/<id>', methods=['POST']) 
def render_script(id=None): 
    ... 
    data = json.loads(request.data) 
    text_list = data.get('text_list') 
    final_file = audio_class.render_audio(data=text_list) 
    # do stuff 
    return Response(
     mimetype='application/json', 
     status=200 
    ) 

Bây giờ, những gì tôi muốn làm là có dòng

final_file = audio_class.render_audio() 

chạy và cung cấp một callback được thực hiện khi trở về phương pháp, trong khi Flask thể tiếp tục xử lý yêu cầu. Đây là nhiệm vụ duy nhất mà tôi cần Flask để chạy không đồng bộ, và tôi muốn một số lời khuyên về cách tốt nhất để thực hiện điều này. Tôi đã xem TwistedKlein, nhưng tôi không chắc là chúng quá mức cần thiết, vì có lẽ Threading sẽ đủ.

Mọi lời khuyên sẽ được đánh giá cao.

EDIT

Hoặc lẽ Celery là một lựa chọn tốt cho việc này?

+0

Tôi thường sử dụng cần tây cho điều này ... nó có thể là quá mức cần thiết nhưng luồng không hoạt động tốt trong môi trường web (iirc ...) –

+0

Phải. Yeah - Tôi chỉ đang điều tra Celery. Nó có thể là một cách tiếp cận tốt. Dễ dàng thực hiện với Flask? –

+0

heh tôi có xu hướng sử dụng một máy chủ socket cũng (flask-socketio) và có tôi nghĩ rằng nó là khá dễ dàng ... phần khó nhất là nhận được tất cả mọi thứ được cài đặt –

Trả lời

24

Tôi sẽ sử dụng Celery để xử lý tác vụ không đồng bộ cho bạn. Bạn sẽ cần phải cài đặt một nhà môi giới để phục vụ như là hàng đợi công việc của bạn (RabbitMQ và Redis được khuyến khích).

app.py:

from flask import Flask 
from celery import Celery 

broker_url = 'amqp://[email protected]'   # Broker URL for RabbitMQ task queue 

app = Flask(__name__)  
celery = Celery(app.name, broker=broker_url) 
celery.config_from_object('celeryconfig')  # Your celery configurations in a celeryconfig.py 

@celery.task(bind=True) 
def some_long_task(self, x, y): 
    # Do some long task 
    ... 

@app.route('/render/<id>', methods=['POST']) 
def render_script(id=None): 
    ... 
    data = json.loads(request.data) 
    text_list = data.get('text_list') 
    final_file = audio_class.render_audio(data=text_list) 
    some_long_task.delay(x, y)     # Call your async task and pass whatever necessary variables 
    return Response(
     mimetype='application/json', 
     status=200 
    ) 

Chạy ứng dụng Flask của bạn, và bắt đầu một quá trình để chạy công nhân cần tây bạn.

$ celery worker -A app.celery --loglevel=debug 

Tôi cũng sẽ tham khảo hướng dẫn chi tiết hơn về cách sử dụng cần tây với bình đựng của Miguel Gringberg.

+0

Có, điều này giống như cách để đi. Cảm ơn! Và cảm ơn cho đoạn mã. –

-3

Tôi đề xuất thay đổi về kiến ​​trúc. Tôi sẽ xem xét việc sử dụng ZeroRPC cùng với mặt tiền giao diện RESTFul.

+6

Tại sao ZeroRPC tốt hơn bình? – shrewmouse

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