请问 Django 在启动的时,如何执行一次性业务代码?

2021-11-10 17:44:11 +08:00
 Phishion

我尝试过各大网站转载的“放在 urls 文件里执行”的办法,但是很不幸,我发现会执行多次。

具体业务就是设计了一个 Redis Set 队列控制并发,任务正常运行的时候是可以加入、弹出的,但是如果任务在运行过程中发生死机,或者其它未知的 Django 整体崩溃,虽然概率很小,但是一旦发生这个队列就会产生脏数据,我现在是考虑启动 Django 的时候,自动清空这个队列,但是就要求这个函数仅运行一次,如果实现不了,我就只能考虑其他办法。

请问有什么其他方法能让我的业务代码在启动的时候就运行一次么?

3359 次点击
所在节点    Django
27 条回复
rationa1cuzz
2021-11-10 17:48:54 +08:00
Django 启动执行任务吗?中间件了解一下
SmiteChow
2021-11-10 17:52:54 +08:00
1. 判断是否“产生脏数据”
2. 再重置数据

逻辑应该是这样的,而不是次数问题
676529483
2021-11-10 17:54:47 +08:00
放在 url 里确实执行一次,但是是一个进程执行一次。用 uwsgi 或者 gunicorn 启动多个进程会发生这个问题。
从只执行一次的角度,需要别的进程来做,比如 celery 、job 平台等。
但我感觉你说的业务场景,可以适当修改下更好,比如执行队列数据时,发现历史脏数据就清除掉
NaVient
2021-11-10 18:00:49 +08:00
manage.py 不是有 main 函数吗?
huazhaozhe
2021-11-10 18:02:19 +08:00
redis 本身不就可以做嘛
另外这个很奇怪啊,如果要清空队列那不是任务就没了,那我崩溃了几次就清除几次和一次启动清除了几次有啥区别,脏数据嘛用其他方式解决,保证重复任务也没问题这样子?
Phishion
2021-11-10 18:04:15 +08:00
@SmiteChow 判断是否有脏数据就要查表,我可以接受启动的时候查询一次是否有脏数据,但是我不能隔段时间就轮询一次数据库,所以还是要解决如何让它只启动一次的问题。
Phishion
2021-11-10 18:07:43 +08:00
@huazhaozhe 崩溃其实是极端条件,我外面全部 try 包来了,可以保证任务是否成功都能安全退出队列,另外请问 redis 本身怎么做?我任务队列要持久化的,对应的 Key 肯定不能设置超时
freakxx
2021-11-10 18:08:09 +08:00
我尝试过各大网站转载的“放在 urls 文件里执行”的办法,但是很不幸,我发现会执行多次。

。。。这种做法完全就是傻逼的做法,把业务代码扔到 router ,无论代码能不能跑都是不对的

-----

django 是以 app 为基本单位划分业务逻辑,
你需要执行的代码,放在 apps.py 里面做执行
具体搜下 django app run code once 之类的关键词

找到的结果大概这样
https://pythonin1minute.com/where-to-put-django-startup-code/
Phishion
2021-11-10 18:14:46 +08:00
@676529483 感谢回复,你这个方法是最稳的,但是这块儿代码我想让它 15 秒轮询一次,因为除非是极端条件,否则根本不会出现这样的事情,所以想尽量不查表完成,当然也不是必须,如果我没找到好的方法就按常规的解决。
Phishion
2021-11-10 18:15:23 +08:00
@freakxx 感谢回复,我找找
vicalloy
2021-11-10 18:20:44 +08:00
写个 django 从 command ,在 crontab 里定时调用。
chuanqirenwu
2021-11-10 18:50:24 +08:00
重写 get_asig_application 或者 get_wsgi_application 方法,在 django.setup 后执行校验逻辑,另外可以看下 django 的 system check 系统,应该有相应的 hook 。
tomczhen
2021-11-10 19:40:28 +08:00
kidblg
2021-11-10 19:41:36 +08:00
面向可维护的开发吧,得考虑后来接手人的感受。
wuwukai007
2021-11-10 19:56:13 +08:00
放在 wsgi 然后 gunicorn 启动的时候指定 --preload
zengxs
2021-11-10 20:31:11 +08:00
通过 Django 的中间件,用 APScheduler 启动一个定时任务

https://gist.github.com/zengxs/f3d0d1a894587af929fed835d4d78bbd
GTim
2021-11-10 21:10:31 +08:00
adoal
2021-11-10 21:18:13 +08:00
没有运维知识的纯程序员往往会把什么乱七八糟的需求都用项目的主编程语言写到主程序里面去。其实呢,你的程序在生产环境运行时,可以外面包一个 sh 脚本来启动,把清理数据的操作单独写一个几行的 py 在 django 之前运行不就可以了嘛。
naijoag
2021-11-10 21:44:26 +08:00
def ready
Phishion
2021-11-10 22:45:09 +08:00
感谢各位回复,我来想一个优雅的方法解决这个问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/814479

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX