Python 异步芹菜任务开销

Python 异步芹菜任务开销,python,rabbitmq,celery,gunicorn,flask-mail,Python,Rabbitmq,Celery,Gunicorn,Flask Mail,我正在使用此代码发送数千封电子邮件的通知。在运行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) 所以我在考虑使用密件抄送,但后来我意识到我不能,因为每

我正在使用此代码发送数千封电子邮件的通知。在运行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)


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

编辑2:根据2ps的答案进行更改后,现在循环速度很快,但在循环执行几秒钟后,web服务器仍处于锁定状态

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

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


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

html电子邮件呈现是开销——如果您想让调用者更快地执行此操作,请将模板呈现移到芹菜任务中

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

经过数小时的重构,现在循环速度很快,但我也遇到了同样的问题。请将循环也推迟到芹菜上,否则您将锁定线程以每个用户创建一个芹菜任务,在此期间,Web服务器无法处理任何请求。@AnthonyPerot循环后的服务器响应现在几乎是瞬时的。然而,几秒钟后,gunicorn将停止,这是最初的问题。我不知道如何调试这个诚实的系统。一次吸引所有用户看起来不太好。在服务器端这样做看起来也不太好。所以,您应该有一个芹菜任务,您应该从您的Web服务器启动,然后您应该有一个任务启动其他发送电子邮件任务。在从数据库中提取所有用户时,还应该使用分页。接下来,当您只使用电子邮件时,为什么要提取所有字段?您应该降低用户查询的占用空间
@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)