V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
resolvewang
V2EX  ›  问与答

celery 定时任务如何不延迟执行

  •  
  •   resolvewang · 2017-04-27 21:35:57 +08:00 · 3756 次点击
    这是一个创建于 2555 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在使用 celery 做定时任务的时候,比如下面代码

    app.conf.beat_schedule = {

    'test_celery': {
    
        'task': 'tasks.login.test_timertask',
        
        'schedule': 60.0,
    }
    

    }

    在使用 "celery beat -A tasks.login --loglevel=info"后,会延迟 60 秒才执行第一次任务。请问一下,怎么写能让它在刚启动定时任务的时候就执行,然后每过 60s 再次执行?

    9 条回复    2017-04-28 16:49:13 +08:00
    gulu
        1
    gulu  
       2017-04-28 00:15:52 +08:00 via Android
    在启动的时候就 test_timertask.delay() 一下?
    ryd994
        2
    ryd994  
       2017-04-28 06:15:45 +08:00 via Android   ❤️ 1
    我觉得这样设计是合理的
    一不小心挂了重启的话不会出事
    resolvewang
        3
    resolvewang  
    OP
       2017-04-28 10:08:24 +08:00
    @gulu 是的,我是想在启动的时候就调用 test_timertask()这个方法。你的意思是直接再通过客户端手动调用一次 test_timertask()?
    gulu
        4
    gulu  
       2017-04-28 10:10:41 +08:00 via Android   ❤️ 1
    我觉得 2 楼说的在理。
    还有一种思路是自己写 beat 的 database
    你可以搜索关键字 celery add periodic task dynamically
    resolvewang
        5
    resolvewang  
    OP
       2017-04-28 10:11:41 +08:00
    @ryd994 我的情况是这样的:由于一个爬虫需要周期性的获取到 cookie。所以我想做一个定时登录的模块,不可能让抓取程序都运行了过后,登录模块还没运行吧。所以我想在 beat 启动的时候就调用 login 的方法。

    经过您的提醒,我觉得这样设计好像是有道理的。所以第一次调用 login 就必须再使用一个命令给 worker 发送任务吗?
    ryd994
        6
    ryd994  
       2017-04-28 11:47:19 +08:00 via Android   ❤️ 1
    @resolvewang 初始化的时候手动执行一次可以么?
    或者我看到 celery 有个 crontab schedule,可能有用
    或者抓取程序判断一下是否为空

    为了防止我之前提到的问题,启动时不要开抓取任务,等 crontab 执行过再开
    cron 看的是时钟,所以就算重启,只要不在 1 分钟内,也会等到下次计划才执行
    resolvewang
        7
    resolvewang  
    OP
       2017-04-28 14:49:03 +08:00
    @ryd994 这样的话我必须手动判断登录任务是否执行了吗?有不有啥可以自动判断的方法,让登录执行完成后我就可以马上执行抓取任务?
    实际情况是这样的:我要定时登录微博做数据采集,微博的 cookie 是 24 小时失效,我就必须每天让(多个)账号登录一到两次(如果频繁做模拟登陆也会被封号),每次成功登录后把 cookie 存入 redis。如果我设置 crontab(minite=0, hour='*/10')的话,它会在 10 的倍数的整点执行登录任务吧。比如我在早上 11 点执行了 beat,那么得等到晚上 20 点登录任务才会被 worker 执行吧。第一次执行抓取任务也得等到晚上 20 点过后了吗?并且我到了那个点(晚 8 点)还要手动在命令行输入 "celery -A login worker" 来启动 worker 吗?

    感谢耐心解答,我最近才接触 celery 和分布式的东西,问题比较多,感谢多多包涵。
    ryd994
        8
    ryd994  
       2017-04-28 15:45:37 +08:00
    @resolvewang
    让登录任务去解锁抓取任务啊

    既然存入 Redis 的话,检查一下是不是为空不就好了么?如果担心过期的话,就把时间也存上
    如果为空就失败等重试,或者报错死等
    这种几个小时跑一次的任务甚至不需要在 celery 里做,系统 crontab 就行,反正最后存 redis
    启动的时候先检查一下有没有过期或者登录服务是不是活着,如果登录服务死了报错也是一种办法

    保证只有一个进程写的话就没有问题。不要让每个 worker 自己去触发登录,否则就要处理缓存雪崩问题
    resolvewang
        9
    resolvewang  
    OP
       2017-04-28 16:49:13 +08:00
    @ryd994 是的,确实可以直接用 crontab,但是服务器是 windows。我想使用 celery 来调度抓取任务,因为抓取是需要长时间运行的,为了提高抓取效率,所以使用 celery 做分布式任务调度。先前我是直接在存 cookie 的时候设置了过期时间,也是通过轮询 redis 检查是否有有效 cookie 可用。

    感谢回答!感觉收获了不少。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4985 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 09:45 · PVG 17:45 · LAX 02:45 · JFK 05:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.