在使用 celery 做定时任务的时候,比如下面代码
app.conf.beat_schedule = {
'test_celery': {
'task': 'tasks.login.test_timertask',
'schedule': 60.0,
}
}
在使用 "celery beat -A tasks.login --loglevel=info"后,会延迟 60 秒才执行第一次任务。请问一下,怎么写能让它在刚启动定时任务的时候就执行,然后每过 60s 再次执行?
1
HFcbyqP0iVO5KM05 2017-04-28 00:15:52 +08:00 via Android
在启动的时候就 test_timertask.delay() 一下?
|
2
ryd994 2017-04-28 06:15:45 +08:00 via Android 1
我觉得这样设计是合理的
一不小心挂了重启的话不会出事 |
3
resolvewang OP @gulu 是的,我是想在启动的时候就调用 test_timertask()这个方法。你的意思是直接再通过客户端手动调用一次 test_timertask()?
|
4
HFcbyqP0iVO5KM05 2017-04-28 10:10:41 +08:00 via Android 1
我觉得 2 楼说的在理。
还有一种思路是自己写 beat 的 database 你可以搜索关键字 celery add periodic task dynamically |
5
resolvewang OP @ryd994 我的情况是这样的:由于一个爬虫需要周期性的获取到 cookie。所以我想做一个定时登录的模块,不可能让抓取程序都运行了过后,登录模块还没运行吧。所以我想在 beat 启动的时候就调用 login 的方法。
经过您的提醒,我觉得这样设计好像是有道理的。所以第一次调用 login 就必须再使用一个命令给 worker 发送任务吗? |
6
ryd994 2017-04-28 11:47:19 +08:00 via Android 1
@resolvewang 初始化的时候手动执行一次可以么?
或者我看到 celery 有个 crontab schedule,可能有用 或者抓取程序判断一下是否为空 为了防止我之前提到的问题,启动时不要开抓取任务,等 crontab 执行过再开 cron 看的是时钟,所以就算重启,只要不在 1 分钟内,也会等到下次计划才执行 |
7
resolvewang OP @ryd994 这样的话我必须手动判断登录任务是否执行了吗?有不有啥可以自动判断的方法,让登录执行完成后我就可以马上执行抓取任务?
实际情况是这样的:我要定时登录微博做数据采集,微博的 cookie 是 24 小时失效,我就必须每天让(多个)账号登录一到两次(如果频繁做模拟登陆也会被封号),每次成功登录后把 cookie 存入 redis。如果我设置 crontab(minite=0, hour='*/10')的话,它会在 10 的倍数的整点执行登录任务吧。比如我在早上 11 点执行了 beat,那么得等到晚上 20 点登录任务才会被 worker 执行吧。第一次执行抓取任务也得等到晚上 20 点过后了吗?并且我到了那个点(晚 8 点)还要手动在命令行输入 "celery -A login worker" 来启动 worker 吗? 感谢耐心解答,我最近才接触 celery 和分布式的东西,问题比较多,感谢多多包涵。 |
8
ryd994 2017-04-28 15:45:37 +08:00
@resolvewang
让登录任务去解锁抓取任务啊 既然存入 Redis 的话,检查一下是不是为空不就好了么?如果担心过期的话,就把时间也存上 如果为空就失败等重试,或者报错死等 这种几个小时跑一次的任务甚至不需要在 celery 里做,系统 crontab 就行,反正最后存 redis 启动的时候先检查一下有没有过期或者登录服务是不是活着,如果登录服务死了报错也是一种办法 保证只有一个进程写的话就没有问题。不要让每个 worker 自己去触发登录,否则就要处理缓存雪崩问题 |
9
resolvewang OP @ryd994 是的,确实可以直接用 crontab,但是服务器是 windows。我想使用 celery 来调度抓取任务,因为抓取是需要长时间运行的,为了提高抓取效率,所以使用 celery 做分布式任务调度。先前我是直接在存 cookie 的时候设置了过期时间,也是通过轮询 redis 检查是否有有效 cookie 可用。
感谢回答!感觉收获了不少。 |