Python:何时返回响应代码?

时间:2016-09-02 03:41:05

标签: rest flask python-3.5 gevent

我有一个接受用户输入的API,并在后面进行大量处理。我的问题是,我应该在输入验证后返回响应代码(200)还是应该等到输入处理(保存到mysql,格式化输入,保存到redis等)结束?

示例代码:

# Should I wait for the greenlets to finish processing - which might take a long time?
@app.route('/messages', methods=['POST'])
def send_message():
    user_input = flask.request.form.get('user_input')

    if user_is_valid() and user_input_is_valid(user_input):
        process_input = [gevent.spawn(format_input_and_save_to_mysql, user_input),
                         gevent.spawn(format_input_and_save_to_redis, user_input)]
        gevent.join_all(process_input)
        return 'Processing done', 200

    return 'Unauthorized', 401

# Or should I return immediately even though the processing is still being done?
@app.route('/messages', methods=['POST'])
def send_message():
    user_input = flask.request.form.get('user_input')

    if user_is_valid() and user_input_is_valid(user_input):
        gevent.spawn(format_input_and_save_to_mysql, user_input)
        gevent.spawn(format_input_and_save_to_redis, user_input)
        return 'Processing done', 200

    return 'Unauthorized', 401

1 个答案:

答案 0 :(得分:1)

您应该考虑返回响应的含义:当浏览器收到服务器的响应时,浏览器认为他的请求已完成,重定向或以某种方式失败。

因此,您应该针对每个特定情况考虑这个问题。如果在所有任务结束时需要处理请求的结果,则可能需要等待所有过程完成并返回结果或合适的状态代码(如果其中一个子任务失败)。

但是,如果这些任务真的长时间运行(例如几秒钟),则可能因请求超时而遇到麻烦。如果是这样,有几种技术可以解决这个问题,比如使用区间轮询,长轮询或websockets。

每种轮询都将在前端实现,这意味着浏览器需要向服务器询问新内容或数据。因此,当长时间运行的任务启动时,您将从服务器返回响应。在浏览器中分析此响应将开始针对给定的API端点进行轮询。根据长时间运行任务的进度,您可能会返回给定状态或已处理数据并停止轮询。如果没有完成这些过程,你可以返回类似于"仍在运行"状态和再次轮询。因此,轮询将导致来自浏览器的多个请求以及来自服务器的适当响应。

相比之下,Websockets提供服务器和浏览器之间的实时通信,因为浏览器和服务器都能够在websockets连接上引发所谓的事件。

在一天结束时,您需要确定您真正需要的是什么。 Websockets真的很棒,但如果你是初学者,恕我直言有点棘手。但是,有一个关于如何implement websockets using Flask and gevent的例子。但是,您需要记住一件大事。通过轮询或websockets请求这些服务器任务的进度时,您需要确保从这些任务中获取状态或进度消息是完全不同的事情。如果您需要一个起点,我建议您查看一个任务队列,例如Celery