我有一个独立的脚本,可以抓取页面,启动与数据库的连接,并将数据库写入其中。我需要它在x小时后定期执行。我可以使用伪代码使用bash脚本:
while true
do
python scraper.py
sleep 60*60*x
done
从我读到的关于消息代理的内容来看,它们用于发送"信号"从一个正在运行的程序到另一个正在运行的程序。就像我有一段代码接受来自用户的电子邮件ID一样,它会将带有email-id的信号发送到另一段将发送电子邮件的代码。
我需要芹菜在heroku上执行定期任务。我已经在一个单独的服务器上有一个mongodb。为什么我需要为rabbitmq或redis运行另一台服务器呢?我可以在没有经纪人的情况下使用芹菜吗?
答案 0 :(得分:10)
Celery体系结构旨在跨多个服务器扩展和分配任务。对于像你这样的网站,这可能是一种过度杀伤力。通常需要队列服务来维护任务列表并发出已完成任务的状态。
你可能想看看Huey。 Huey is small-scale Celery "Clone" needing only Redis as an external dependency,而不是RabbitMQ。它仍然使用Redis队列机制来排队队列中的任务。
还存在Advanced Python scheduler甚至不需要Redis,但可以在进程内保存队列中的队列状态。
或者,如果您有非常少量的定期任务,没有延迟任务,我只会使用Cron和纯Python脚本来运行任务。
答案 1 :(得分:2)
正如芹菜documentation所解释的那样:
Celery通过消息进行通信,通常使用经纪人在客户和工作人员之间进行调解。要启动任务,客户端会向队列添加一条消息,然后代理会将该消息传递给工作人员。
您可以将现有的MongoDB数据库用作代理。见Using MongoDB。
答案 2 :(得分:1)
对于这样的应用程序,最好使用Django Background Tasks ,
安装 从PyPI安装:
pip install django-background-tasks
添加到INSTALLED_APPS:
INSTALLED_APPS = (
# ...
'background_task',
# ...
)
迁移数据库:
python manage.py makemigrations background_task
python manage.py migrate
要注册任务,请使用后台装饰器:
from background_task import background
from django.contrib.auth.models import User
@background(schedule=60)
def notify_user(user_id):
# lookup user by id and send them a message
user = User.objects.get(pk=user_id)
user.email_user('Here is a notification', 'You have been notified')
这会将notify_user转换为后台任务功能。当您从常规代码调用它时,它将实际上创建一个Task对象并将其存储在数据库中。然后,数据库包含有关哪些功能稍后实际需要运行的序列化信息。这确实对调用函数时可以传递的参数施加了限制-它们都必须全部可序列化为JSON。因此,为什么在上面的示例中传递了user_id而不是User对象。
正常调用notify_user会将原先的函数安排在60秒后运行:
notify_user(user.id)
这是默认的计划时间(在装饰器中设置),但是可以被覆盖:
notify_user(user.id, schedule=90) # 90 seconds from now
notify_user(user.id, schedule=timedelta(minutes=20)) # 20 minutes from now
notify_user(user.id, schedule=timezone.now()) # at a specific time
您现在也可以在同步模式下运行原始功能:
notify_user.now(user.id) # launch a notify_user function and wait for it
notify_user = notify_user.now # revert task function back to normal function.
用于测试。 您可以在安排任务时指定详细名称和创建者:
notify_user(user.id, verbose_name="Notify user", creator=user)