我有一个备用脚本,它可以抓取页面,启动到数据库的连接,并将数据库写入其中。我需要它在x小时后定期执行。我可以使用bash脚本,使用伪代码:
while true
do
python scraper.py
sleep 60*60*x
done
从我读到的关于消息代理的内容来看,它们用于将"信号"从一个正在运行的程序发送到另一个程序,原则上就像HTTP一样。就像我有一段接受用户电子邮件id的代码一样,它会向另一段发送电子邮件的代码发送带有电子邮件id的信号。
我需要芹菜在heroku上运行定期任务。我已经在一个单独的服务器上有了一个mongodb。为什么我需要为rabbitmq或redis运行另一个服务器?我可以在没有经纪人的情况下使用芹菜吗?
Celery体系结构旨在跨多个服务器扩展和分配任务。对于像你这样的网站来说,这可能有些过头了。通常需要队列服务来维护任务列表并通知已完成任务的状态。
你可能想去休伊看看。Huey是一个小规模的Celery"克隆",只需要Redis作为外部依赖,而不需要RabbitMQ。它仍然使用Redis队列机制来排列队列中的任务。
还有Advanced Python调度器,它甚至不需要Redis,但可以在进程中保持内存中的队列状态。
或者,如果你有少量的周期性任务,没有延迟的任务,我只会使用Cron和纯Python脚本来运行这些任务。
正如Celery文档所解释的:
Celery通过消息进行通信,通常使用代理在客户端和工作人员之间进行调解。为了启动任务,客户端向队列中添加一条消息,然后代理将消息传递给工作人员。
您可以使用现有的MongoDB数据库作为代理。请参阅使用MongoDB。
对于这样的应用程序,最好使用Django后台任务,
安装从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)
这是默认的计划时间(在decorator中设置),但它可以被覆盖:
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)