我有一个运行uwsgi(有10个工人)+ ngnix的django应用程序。我正在使用apscheduler进行调度。每当我安排一份工作时,它都会被执行多次。从这些答案ans1,ans2我知道这是因为调度程序是在每个uwsgi工作者中启动的。我按照answer中的建议将调度程序绑定到套接字,并通过在db中保持状态来完成调度程序的条件初始化,这样只会启动一个调度程序实例,但仍存在相同的问题,有时候,在创建作业时,发现调度程序没有运行,并且作业保持挂起而不执行。
我正在使用以下代码在django应用程序的URL中初始化apscheduler。这将在应用程序启动时启动调度程序。
def job_listener(ev):
print('event',ev)
job_defaults = {
'coalesce': True,
'max_instances': 1
}
scheduler = BackgroundScheduler(job_defaults=job_defaults, timezone=TIME_ZONE, daemon=False)
scheduler.add_jobstore(MongoDBJobStore(client=client), 'default')
scheduler.add_executor(ThreadPoolExecutor(), 'default')
scheduler.add_executor(ProcessPoolExecutor(),'processpool')
scheduler.add_listener(job_listener)
def initialize_scheduler():
try:
if scheduler_db_conn.find_one():
print('scheduler already running')
return True
scheduler.start()
scheduler_db_conn.save({'status': True})
print('---------------scheduler started --------------->')
return True
except:
return False
我使用以下代码创建作业。
from scheduler_conf import scheduler
def create_job(arg_list):
try:
print('scheduler status-->',scheduler.running)
job = scheduler.add_job(**arg_list)
return True
except:
print('error in creating Job')
return False
我无法正确配置和运行调度程序。我已经提到了apschedule中的所有主题,但仍然没有得到解决方案。
这是解决方案吗?
答案 0 :(得分:3)
让我们考虑以下事实:
(1)默认情况下,UWSGI将您的Django App预先加载到UWSGI主进程中。记忆之前分叉其工人。
(2)UWSGI" forks"来自主人的工人,意味着他们基本上被复制到每个工人的记忆中。由于fork()
的实现方式,Child进程(即worker)不会继承Parent的线程。
(3)当你调用BackgroundScheduler.start()
时,会创建一个线程,负责在任何worker / master调用此函数时执行作业。
在创建任何工作人员之前,您必须在主要流程上致电 要做到这一点,只需确保在实例化应用程序的任何函数/模块中调用 <强>缺陷:强> 在django应用程序的网址中不要&#34; initializ [e] apscheduler ....这将在应用程序启动时启动调度程序。&#34; 这些可能是由每个工作人员加载,因此 不要在"lazy-app&#34;中启动UWSGI服务器。模式,这将在每个工人创建后加载应用程序。 不要使用默认(内存)jobstore运行BackgroundScheduler。这将在所有工人之间产生裂脑综合症。对于在作业上执行的所有CRUD操作,您希望像MongoDB一样强制执行单点事实。 This post可能只会在Gunicorn(WSGI服务器)环境中为您提供更多详细信息。BackgroundScheduler.start()
。通过这样做,当创建工作程序时,它们不会继承BackgroundScheduler线程(上面的#2),因此不会执行任何作业(但它们仍然可以通过与jobstore通信来安排/修改/删除作业!)。 / p>
BackgroundScheduler.start()
。例如,在以下Django项目结构中,我们(可能)希望在wsgi.py
中执行此代码,这是UWSGI服务器的入口点。:mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
start()
被执行多次。
答案 1 :(得分:0)
假设您想在应用程序中使用默认作业存储和默认执行程序运行 BackgroundScheduler:
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
这将为您提供一个 BackgroundScheduler,其 MemoryJobStore 名为“default”,ThreadPoolExecutor 名为“default”,默认最大线程数为 10。
现在,假设您想减少线程数,并且还想调整新作业的默认值并设置不同的时区。以下示例将为您提供:
from pytz import utc
from apscheduler.schedulers.background import BackgroundScheduler
job_defaults = {
'coalesce': False,
'max_instances': 3
}
scheduler = BackgroundScheduler(job_defaults=job_defaults, timezone=utc)