谢谢。
您可以设置一个定时任务来运行您定义的函数,或者 - 更高级且可能更推荐的方法是,在您的项目中集成celery(实际上非常简单)。
当WSGI脚本被首次导入时,您可以从该脚本创建一个后台线程。
import threading
import time
def do_stuff():
time.sleep(60)
... do periodic job
_thread = threading.Thread(target=do_stuff)
_thread.setDaemon(True)
_thread.start()
为了使这个方法生效,你必须仅使用一个守护进程,否则每个进程都会执行相同的操作,这可能不是你想要的。
如果你在守护进程组中使用多个进程,另一种方法是创建一个特殊的守护进程组,其唯一目的是运行此后台线程。换句话说,进程实际上不会接收任何请求。
你可以通过以下方式实现:
WSGIDaemonProcess django-jobs processes=1 threads=1
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
process-group=django-jobs application-group=%{GLOBAL}
WSGIImportScript指令表示在进程组“django-jobs”的上下文中加载并运行该脚本。
为了避免多个脚本,我将其指向了您用于WSGIScriptAlias的原始WSGI脚本文件。但是我们不希望它在被该指令加载时运行,因此我们执行以下操作:
import mod_wsgi
if mod_wsgi.process_group == 'django-jobs':
_thread = threading.Thread(target=do_stuff)
_thread.setDaemon(True)
_thread.start()
在这里,它查看守护进程组的名称,并且仅在使用专门为此单独设置的单一进程的特殊守护进程组内启动时才运行。
总体而言,您只是将Apache用作大型过程管理器,尽管已知其具有鲁棒性。由于此进程将消耗额外的内存,因此这有点过度杀伐,但根据您所做的工作的复杂性,它仍然可能有用。
做这件事的一个可爱之处在于,由于其中仍然是完整的Django应用程序,您可以将特定的URL映射到此进程,从而提供远程API来管理或监视后台任务及其正在做的事情。
WSGIDaemonProcess django-jobs processes=1 threads=1
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \
process-group=django-jobs application-group=%{GLOBAL}
WSGIDaemonProcess django-site processes=4 threads=5
WSGIScriptAlias / /usr/local/django/mysite/apache/django.wsgi
WSGIProcessGroup django-site
WSGIApplicationGroup %{GLOBAL}
<Location /admin>
WSGIProcessGroup django-jobs
</Location>
在这里,除了/admin下的内容运行在“django-jobs”中,其他所有URL都在“django-site”中运行。
无论如何,这解决了根据请求在Apache mod_wsgi守护程序进程中执行的具体问题。
正如所指出的,另一种方法是使用命令行脚本设置和加载Django并执行工作,然后从cron作业中执行该脚本。命令行脚本意味着偶尔会有瞬时内存使用,但作业的启动成本更高,因为每次需要加载所有内容。
when_ready
函数来启动新线程。以下是一个示例:https://github.com/benoitc/gunicorn/blob/master/examples/example_config.py - Mridang Agarwalla我之前使用过cron job,但是我告诉你,过一段时间你会转向celery。
Celery是正确的选择。此外,您可以将长时间的异步进程分配任务,以便加快请求/响应时间。