为什么这个简单的Flask脚本需要这么长时间才能运行?

时间:2019-02-07 23:25:49

标签: amazon-web-services flask amazon-elastic-beanstalk

这只是一个在提交表单后发送邮件的脚本:

@application.route('/contact', methods=['GET', 'POST'])
def send():
    if request.method == 'POST':
        first_name = request.form['first_name']
        last_name = request.form['last_name']
        email = request.form['email']
        msg = Message('Hey!', sender='example@example.com', recipients=['example@example.com'])
        msg.body = email + " " + first_name + " " + last_name + " "
        mail.send(msg)
        msg2 = Message('Hello', sender='example@example.com', recipients=[email])
        msg2.body = "Hi " + first_name + ". Thanks for requesting access to our beta. We'll contact you soon to schedule a call."
        mail.send(msg2)

        return render_template('contact.html')

    return render_template ('index.html')

这两封电子邮件均已发送,但是处理脚本的时间太长,这导致较少的注册。怎么了?

以防万一,我将这个Flask应用程序托管在Elastic Beanstalk实例上。

1 个答案:

答案 0 :(得分:1)

发送电子邮件是一项耗时的操作。如果启用日志,则可以看到进行了多次调用。 这与AWS或您的服务器无关。

在烧瓶应用中,发送电子邮件应该是asynchronous的任务。

有很多方法可以做到这一点。 您可以简单地重构代码并使用@async装饰器编写函数,flask mega tutorial的细节很好。

#[...other imports...]
from threading import Thread

def async(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper

@async
def send_async_email(app, msg):
    with app.app_context():
        mail.send(msg)

@application.route('/contact', methods=['GET', 'POST'])
def send():
    if request.method == 'POST':
        first_name = request.form['first_name']
        last_name = request.form['last_name']
        email = request.form['email']
        msg = Message('Hey!', sender='example@example.com', recipients=['example@example.com'])
        msg.body = email + " " + first_name + " " + last_name + " "
        send_async_email(application, msg)
        msg2 = Message('Hello', sender='example@example.com', recipients=[email])
        msg2.body = "Hi " + first_name + ". Thanks for requesting access to our beta. We'll contact you soon to schedule a call."
        send_async_email(application, msg)

        return render_template('contact.html')

    return render_template ('index.html')

由于您是在AWS上运行应用程序,因此也可以使用SES代替Flask-Mail。

其他解决方案是使用message queue,例如RabbitMQ,但这将涉及编写更多代码。

所有这些解决方案将使电子邮件在后台发送,从而使flask应用程序无需等待发送电子邮件即可将响应返回给客户端。