项目开发过程中因为功能需求新增了定时任务,使用flask_apscheduler,查看源代码后,发现跟apscheduler的使用方式其实是一样的,只是套flask壳。本地测试的时候定时任务是没什么问题的,本地服务用单进程单线程启动,但是部署到云服务器的时候,使用多进程启动服务,出现了数据库出现重复数据,且手机短信预警消息多次下发的情况。
排查复测后,发现是多进程启动服务导致的,每个进程都启动了一个定时任务。
在国外论坛看大牛们各种花里胡哨的解决办法后,发现最便捷的方法是写一个全局锁,使用全局锁来判定第一个进程启动定时任务后,后续的进程不再启动定时任务。如下,其中fcntl是linux特有的基础包,windows平台是没有这个包的,但是不影响日常开发,毕竟项目最后都是要部署到linux云服务器的。
from flask import Flask
from configs import config
import atexit,fcntl
from flask_apscheduler import APScheduler
applications = Flask(__name__)
applications.config.from_object(config["dev"])
def create_app():
f = open("app/timer/aps.lock", "wb")
try:
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
apscheduler = APScheduler()
apscheduler.init_app(applications)
apscheduler.start()
#这是一个定时任务,也可以在配置文件configs中进行定时任务配置
from app.timer.test import test
apscheduler.add_job(id="test", func=test.test, trigger="interval", minutes=5)
except:
pass
def unlock():
fcntl.flock(f, fcntl.LOCK_UN)
f.close()
atexit.register(unlock)