APSwork 部分内容
redis_connet = redis.Redis(host='localhost', port=6379, db=0)
jobstores = {
'redis': RedisJobStore(),
}
executors = {
'default': ThreadPoolExecutor(4)
}
sched = BackgroundScheduler(jobstores=jobstores, executors=executors)
def open_in(servername,serverip,cmd):
print '{0}--open in ....'.format(servername)
.....
def open_out(servername,serverip,cmd):
print '{0}---open out ....'.format(servername)
.....
def cronKaifu(starttime,servername,serverip,cmd_in,cmd_out):
....
jobstores = {
'redis': RedisJobStore(),
}
executors = {
'default': ThreadPoolExecutor(1)
# 'processpool': ProcessPoolExecutor(3)
}
sched = BackgroundScheduler(jobstores=jobstores, executors=executors)
sched.add_job(func=open_in,args=(servername,serverip,cmd_in,),trigger='date',next_run_time=open_in_time,jobstore='redis',id='{0}_in_{1}'.format(servername,sendtime_timestamp_in))
print sched.get_jobs()
sched.add_job(func=open_out,args=(servername,serverip,cmd_out,),trigger='date',next_run_time=open_out_time,jobstore='redis',id='{0}_out_{1}'.format(servername,sendtime_timestamp_out))
print sched.get_jobs()
sched.start()
views.py 里面调用这个任务
def kaifu_time(request):
....
....
cronKaifu(timeArray,server_name,server_ip,open_in_cmd,open_out_cmd)
......
....
return render(request, 'mt/kaifu_time.html', locals())
添加任务后,两次打印 get_jobs()内容
[<Job (id=mt_ios999game_in_1516005540000 name=open_in)>]
[<Job (id=mt_ios999game_in_1516005540000 name=open_in)>, <Job (id=mt_ios999game_out_1516006260000 name=open_out)>]
到点后,id=mt_ios999game_in_1516005540000,会被执行 2 次,有时候会是 3 次,但有时候又是正常的。
[15/Jan/2018 15:02:22] "POST /mt/kaifu_time/ HTTP/1.1" 302 0
[15/Jan/2018 15:02:22] "GET /mt/kaifu_time HTTP/1.1" 301 0
[15/Jan/2018 15:02:22] "GET /mt/kaifu_time/ HTTP/1.1" 200 19539
mt_ios999game--open in ....
mt_ios999game--open in .... <==这里的打印两次
Exception in thread APScheduler:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/qzdata1/python_env/LazyOps/lib/python2.7/site-packages/apscheduler/schedulers/blocking.py", line 30, in _main_loop
wait_seconds = self._process_jobs()
File "/qzdata1/python_env/LazyOps/lib/python2.7/site-packages/apscheduler/schedulers/base.py", line 981, in _process_jobs
self.remove_job(job.id, jobstore_alias)
File "/qzdata1/python_env/LazyOps/lib/python2.7/site-packages/apscheduler/schedulers/base.py", line 613, in remove_job
raise JobLookupError(job_id)
JobLookupError: u'No job by the id of mt_ios999game_in_1516005540000 was found'
我把两个 add_job()位置互掉后,即先添加 add_job(func=open_out...) 再添加 add_job(func=open_in..)
然后 open_out 会被执行两次。
这样的问题,我应如何修改。
感觉毫无逻辑出现这问题,一次性任务,会被重复执行,而且是同一时间的。
1
oncew 2018-07-30 15:46:46 +08:00
偶然看到这个问题,虽然很久了,但是回复一下可能的原因:你的程序运行的是 debug 模式,或者多进程,多线程模式时候,会有多个 scheduler 实例,这个时候会造成任务多次执行
|
2
fanne OP |
3
oncew 2018-09-06 06:45:16 +08:00
v2ex 的提醒功能做的不好,看其他消息提醒的时候,才注意这个帖子.. 重复执行的原因我能确定是多进程造成的问题,后面看了下 apschedler 的源码,对于多线程的情况是有加锁执行任务的,防止重复执行(希望没记错--),但是多进程的情况,这个线程锁没用,debug 模式(也会多起一个进程监听),后面我尝试加了一个多进程的锁,发现许多坑仍然没有解决,实现的功能也是 celery 已经早就解决的问题,所以我觉得用 celery 是最好的解决方案
|
4
mingxu 2018-09-11 10:42:03 +08:00
相比 APScheduler,celery 不能实现动态添加任务的功能吧。这个问题还有其他的解决办法么?
|
5
boyzhh 2019-11-12 04:01:03 +08:00
我也遇到这个问题了,最简单的提交表格新建记录,经过反复测试,随机性的出现一个 view 同时执行两次,导致报错记录已存在,但因为执行了两次,新的记录也能存入,测试大概是 7-10 次就会出现一次同时执行两次的情况,莫名其妙,关闭了 debug 模式也一样
|