首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
V2EX  ›  Python

Django 启动时如何启动一个新线程

  •  
  •   kaiccc · 31 天前 · 1147 次点击
    这是一个创建于 31 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:Django 在启动时初始化一个子线程,用于在后台轮训心跳任务

    心跳任务,监控其他节点

    目前测试情况:

    1.定时器( apscheduler )的方案,并不是我想要的。比如 任务可能随着节点增多,本来 5 秒能处理完的 job,变成 10 秒。apscheduler 做不到顺延执行同 job (我是没找到办法)

    2.尝试过 在 view 中创建线程,加载的代码没问题,但是创建线程无效果没 log。猜测 manage.py runserver 的时候是 fork 了子进程。

    1. manage.py 中创建线程,会阻塞主进程。

    那位大佬 来指点一下。小弟感谢不尽(抱拳)

    17 回复  |  直到 2019-04-20 20:53:09 +08:00
        1
    wnh3yang   31 天前
    用芹菜队列应该可以
        2
    keepeye   31 天前
    创建线程怎么会阻塞主线程呢?能贴下代码么?

    我用 tornado 也可以创建线程啊

    ```
    # 创建队列处理线程
    threading.Thread(target=handle_queue, name="handle_queue").start()
    # 启动 tornado
    port = os.environ.get('PORT', 8888)
    api.listen(port)
    print('listen on {}'.format(port))
    tornado.ioloop.IOLoop.current().start()
    ```
        3
    phithon   31 天前
    创建线程的操作在哪都不会阻塞主线程吧,是不是你 join 了。。
        4
    wizardoz   31 天前
    好多业务通过 celery 就能做到,但是你问的是如何开线程,把创建线程的代码放在 app 的 __init__.py 中即可,并保证 app 会被 import
        5
    neoblackcap   31 天前
    开两个服务,Python 里面就不要用什么线程,当线程死了就好了。
    还有就是正常一点都不会搞什么 view 中启动线程做心跳检测,你的检查周期跟请求的生命周期绑定?这个设计我只能投反对票。
    还有就是生产环境不会用 manage.py runserver,那个只是给你开发用的。
    如果你生产环境用 uwsgi,那么它已经自带心跳检查了,不知道你的心跳想怎么做,一般 http 的它还是能做的,你可以看看 uwsgi 的文档
        6
    wizardoz   31 天前
    manage.py 中创建线程不科学,manage.py 这个文件只是调试的时候用的,真正部署以后这个文件不会执行。
        7
    myyou   31 天前
    "apscheduler 做不到顺延执行同 job"是什么意思?” misfire_grace_time “参数是你要的吗?
        8
    JamesMackerel   31 天前 via iPhone
    Django crontab
        9
    guyujiezi   31 天前
    首先,你这个解决方案并不恰当,用 supervisor 启动独立守护进程更加合适,不过你的方案要实现也并非不可能。

    django 程序一般会被托管给 WSGI 容器来运行,你在 django 程序中无法预料会是以多进程或是多线程运行,你需要一个全局互斥对象( Mutex )来保证这个线程只被运行一次,可以通过文件锁来实现
        10
    kaiccc   31 天前
    可能说的比较乱。
    我只是想 创建 django 启动时加载一个子线程
        11
    kaiccc   31 天前
    @wizardoz 试过加载 init 中,通过 manage.py 启动项目 会阻塞 启动。(子线程创建没问题,但是子线程里是死循环,来处理业务)
        12
    est   31 天前
    wsgi 架构里 线程是 anti pattern。建议放弃治疗。
        13
    Qzier   31 天前
    首先你要使用 BackgroundScheduler,然后在你 app 下的 apps.py 中的 AppConfig 子类添加 ready 方法,该方法每次应用载入前被启动一次,然后在 INSTALLED_APPS 注册该类名,而不是 app 名。
        14
    kaiccc   31 天前
    @Qzier 我只是想 创建 django 启动时加载一个子线程 ,不需要 apscheduler
        15
    kaiccc   31 天前
    @myyou 触发器每 5 秒执行,但是任务 实际耗时 10 秒。顺延执行,上个耗时 10 秒任务完成后的 5 秒 触发
        16
    Aprilming   31 天前
    django.channles,可以试试,有延时其中任务这个功能,你可以创建一个 5 秒的延时任务,但时间之后,执行任务 ,执行完毕,在去掉创建延时任务的接口。
        17
    hakono   28 天前
    如果只是单纯想要启动时创建个进程的话,直接在对应的 app 的 apps.py 里创建不就好了

    apps.py 的对应 AppConfig 类里的 ready()方法会自动被调用,在 ready()方法里创建进程就行了

    不过有点要注意的是,python manage.py runserver 会启动两个 django 进程,另一个进程是用来监视代码变更动态重启服务的,这个进程也会调用 ready()方法。这里需要自己处理选择检测下,别多次创建进程
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2370 人在线   最高记录 5043   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 18ms · UTC 08:46 · PVG 16:46 · LAX 01:46 · JFK 04:46
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1