首页 > 解决方案 > 异步芹菜任务开销

问题描述

我正在使用此代码为数千封电子邮件发送通知。似乎它在运行 for 循环之后在 Web 服务器(gunicorn)中产生了一些开销。发送电子邮件时一切正常。

users = User.query.all()

for user in users:
    send_email_celery(user.email, gettext(u'New email'), 'users/email/new_data', #plus some parameters)

所以我正在考虑使用密件抄送,但后来我意识到我不能,因为每个用户都有一个唯一的 uuid 退订并且密件抄送在邮件客户端中有一些限制。

那么,使用批量邮件处理此类操作的正确方法是什么?

@celery.task
def send_async_email_celery(msg):
    mail.send(msg)
 
def send_email_celery(to, subject, template, **kwargs):
    countdown = kwargs.get('countdown', 600)
    app = current_app._get_current_object()
    msg = Message(subject, sender=app.config['MAIL_SENDER'], recipients=[to])
    msg.html = render_template(template + '.html', **kwargs)
    send_async_email_celery.apply_async(args=[msg], countdown=countdown)

gunicorn --error-logfile gunicorn-error.log --timeout 600 --max-requests 500 --max-requests-jitter 50 --workers 5 app:app -b localhost:8080

编辑 1:使用 top 进行一些调试后,cpu 未满载。是在几秒钟内暂时停止gunicorn的其他东西。

编辑 2:根据 2ps 的答案进行更改后,现在循环很快,但在循环执行几秒钟后,Web 服务器仍被锁定。

编辑3:尝试将rabbitmq更改为reddis,同样的问题。忽略结果,同样的问题。

编辑4:将用户循环移动到@celery 路由后,问题仍然存在

编辑 5:该问题已通过使用 gevent worker 解决。

标签: pythonrabbitmqcelerygunicornflask-mail

解决方案


html 电子邮件渲染是开销——如果您想让调用者更快地完成此操作,请将模板渲染移动到 celery 任务中。

@celery.task
def send_async_email_celery(subject, from_, to_, template, **kwargs):
    msg = Message(subject, sender=from_, recipients=[to_])
    msg.html = render_template(template + '.html', **kwargs)
    mail.send(msg)
 
def send_email_celery(to, subject, template, **kwargs):
    countdown = kwargs.get('countdown', 600)
    app = current_app._get_current_object()
    from_ = app.config['MAIL_SENDER']
    send_async_email_celery.apply_async(args=[subject, from_, to, template], kwargs=kwargs, countdown=countdown)

推荐阅读