Python APScheduler调度器关于多线程并发的坑

问题描述

是使用的是 BlockingScheduler() ,并同时设置了55个定时任务,都在每天8:00:00启动。结果只有10个任务完成了启动,其余的任务都悄悄咪咪的消失了。

代码如下:

__author__ = "dengxinyan"

import time
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor

def task(x):
    time.sleep(5)
    print('任务', x, datetime.datetime.now())

if __name__ == '__main__':

    scheduler = BlockingScheduler()

    scheduler.add_job(func=task, args=('1',), trigger='cron', hour='10', minute='4', second='0', id='task1')
    scheduler.add_job(func=task, args=('2',), trigger='cron', hour='10', minute='4', second='0', id='task2')
    scheduler.add_job(func=task, args=('3',), trigger='cron', hour='10', minute='4', second='0', id='task3')
    scheduler.add_job(func=task, args=('4',), trigger='cron', hour='10', minute='4', second='0', id='task4')
    scheduler.add_job(func=task, args=('5',), trigger='cron', hour='10', minute='4', second='0', id='task5')
    scheduler.add_job(func=task, args=('6',), trigger='cron', hour='10', minute='4', second='0', id='task6')
    scheduler.add_job(func=task, args=('7',), trigger='cron', hour='10', minute='4', second='0', id='task7')
    scheduler.add_job(func=task, args=('8',), trigger='cron', hour='10', minute='4', second='0', id='task8')
    scheduler.add_job(func=task, args=('9',), trigger='cron', hour='10', minute='4', second='0', id='task9')
    scheduler.add_job(func=task, args=('10',), trigger='cron', hour='10', minute='4', second='0', id='task10')
    scheduler.add_job(func=task, args=('11',), trigger='cron', hour='10', minute='4', second='0', id='task11')
    scheduler.add_job(func=task, args=('12',), trigger='cron', hour='10', minute='4', second='0', id='task12')
    scheduler.add_job(func=task, args=('13',), trigger='cron', hour='10', minute='4', second='0', id='task13')

    scheduler.start()

控制台只会打印启动10个“任务”输出。

特别注意:其他小伙伴要运行上面代码请修改运行时间

问题原因

因为APScheduler调度器线程池默认只有10个线程,当55个任务同事启动,所以只有10个任务拿到了资源可以正常运行。如果这55个任务不是同事运行,其实就不会有这种现象。

解决方法

1、错峰运行

55个任务错开时间运行,这样减少并发,可以降低瞬间大量任务给服务器造成瞬时压力,对高并发要求不高的情况可以考虑这个方案。

2、调度器线程数

通过参数配置,可以增大调度器的线程数、进程数。缺点就是如果并发量太大,短时间对服务器资源造成较大压力。

代码如下:

__author__ = "dengxinyan"

import time
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor

def task(x):
    time.sleep(5)
    print('任务', x, datetime.datetime.now())

if __name__ == '__main__':

    # 配置调度器线程数、进程数
    executors = {
        'default': ThreadPoolExecutor(100),
        'processpool': ProcessPoolExecutor(1)
    }
    scheduler = BlockingScheduler(executors=executors)

    scheduler.add_job(func=task, args=('1',), trigger='cron', hour='10', minute='4', second='0', id='task1')
    scheduler.add_job(func=task, args=('2',), trigger='cron', hour='10', minute='4', second='0', id='task2')
    scheduler.add_job(func=task, args=('3',), trigger='cron', hour='10', minute='4', second='0', id='task3')
    scheduler.add_job(func=task, args=('4',), trigger='cron', hour='10', minute='4', second='0', id='task4')
    scheduler.add_job(func=task, args=('5',), trigger='cron', hour='10', minute='4', second='0', id='task5')
    scheduler.add_job(func=task, args=('6',), trigger='cron', hour='10', minute='4', second='0', id='task6')
    scheduler.add_job(func=task, args=('7',), trigger='cron', hour='10', minute='4', second='0', id='task7')
    scheduler.add_job(func=task, args=('8',), trigger='cron', hour='10', minute='4', second='0', id='task8')
    scheduler.add_job(func=task, args=('9',), trigger='cron', hour='10', minute='4', second='0', id='task9')
    scheduler.add_job(func=task, args=('10',), trigger='cron', hour='10', minute='4', second='0', id='task10')
    scheduler.add_job(func=task, args=('11',), trigger='cron', hour='10', minute='4', second='0', id='task11')
    scheduler.add_job(func=task, args=('12',), trigger='cron', hour='10', minute='4', second='0', id='task12')
    scheduler.add_job(func=task, args=('13',), trigger='cron', hour='10', minute='4', second='0', id='task13')

    scheduler.start()

你可能感兴趣的:(Python,python)