IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 【Django+Apscheduler 开发定时任务模块】【四】 -> 正文阅读

[Python知识库]【Django+Apscheduler 开发定时任务模块】【四】

Django+Apscheduler 开发定时任务模块

目录

    本文章要实现的是Django+Apscheduler 开发定时任务模块,并使用uwsgi+nginx模式部署,
    且能避免多进程下任务重复执行,且能够页面动态操作任务;

一、回顾

上一节添加了页面的三个按钮,以及Apscheduler工具类
【Django+Apscheduler 开发定时任务模块】【一】
【Django+Apscheduler 开发定时任务模块】【二】
【Django+Apscheduler 开发定时任务模块】【三】

二、定义定时任务函数和装饰器

1、任务函数很简单,一个普通函数就好

	def test(*args):
    	# 此处就是你需要执行的任务
    	now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    	print(now + '__这是一个测试的定时任务:' + args[0])

2、使用redis前简单说一下思路,先贴一下uwsgi的配置:

<uwsgi>    
   <socket>127.0.0.1:8997</socket> <!-- 内部端口,自定义 --> 
   <chdir>/Users/PycharmProjects/autojob/</chdir> <!-- 项目路径 -->
   <module>autojob.wsgi</module>  <!-- automan为wsgi.py所在目录名-->
   <processes>4</processes> <!-- 进程数 -->
   <daemonize>uwsgi.log</daemonize> <!-- 日志文件 -->
   <enable-threads>True</enable-threads>
   <preload>True</preload>
   <lazy-apps>True</lazy-apps>
</uwsgi>
可以看到,uwsgi的配置中进程数写了4,这种情况下,如果正常启动我们的项目并且同时启动定时任务,那么每个启动的任务都会在同时执行4次;
也就是说,每个线程中都存在定时任务对象,我们要解决的也正是这个问题。
若是将进程数改为1,这个问题解决了,又迎来新的问题,只有一个进程,项目遇到高并发或者阻塞请求的时候还能够正常运行吗!
我想到的解决方案是使用redis锁来实现多进程下的Apscheduler定时任务,讲一下思路再继续:
	项目启动时同时启动定时任务,还是4个进程;若是有状态为启动的任务,就将任务添加到池子中,也就是每个进程中都有一个池子。
	假设有一个任务test为启动状态,四个进程都有这个任务,频率为每分钟执行一次,相当于四个相同的任务,运行时都会调同一个函数。
	我们写个装饰器,在调用函数之前根据任务触发器和id添加redis锁,抢到锁的进程可以继续执行,没有抢到的进程中将该任务从任务池中删掉,只保留一个,若有多个任务同理;
	到这里还是有问题的,后面再说

3、给任务函数添加装饰器 job_before:

def job_before(func):
    def wrapper(*args, **kwargs):
        from app.job_new import JobAction
        job_state = job_list.objects.filter(id=int(args[1])).values('job_state')[0]['job_state']
        if job_state == 1:
            job_value = cache.get(args[0])
            if job_value:
                JobAction.modify_job(args[0], job_value)
                cache.delete(args[0])
            if get_lock(args[0]):
                if args[2] == 'date' or (job_value and job_value[0] == 'date'):
                    job_list.objects.filter(id=int(args[1])).update(job_state=0)
                func(*args, **kwargs)
            else:
                logger.info('该线程未取到锁,停止该任务!')
                JobAction.stop_job(args[0])
        else:
            JobAction.stop_job(args[0])
    return wrapper

def get_lock(lock_name):
    lock = cache.lock('lock.' + lock_name, timeout=5)
    return lock.acquire(blocking=False)
解释一下这个装饰器,
每次运行任务时都要先查看该任务在数据库的状态,若是停止状态那就不执行,直接从池中删除;
(因为4个进程,不可能每次操作都能准确的使用到有该任务的进程,若在该进程就直接停止了,若不在会在下次执行的时间节点停止;)
若是运行状态还是要检查redis是否有该任务的修改策略,有的话先修改池中任务的策略,并且执行本次任务;
(这里可以根据个人情况修改;若想尽快执行任务,也可以直接将该条任务置为停止,在添加一条数据使用该任务触发器;)
date类型的任务执行完成后默认就不会再执行了,所以这了写了date类型任务直接将数据改为了停止状态,并且运行本次任务;
锁的超时时间根据个人情况修改

4、修改任务函数

	给函数添加装饰器
	@job_before
	def test(*args):
    	# 此处就是你需要执行的任务
    	now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    	print(now + '__这是一个测试的定时任务:' + args[0])

整个项目大概就这么多了,几乎所有的代码都在这了,写的很粗糙,大家自己拼一拼吧。
我还要再整理一下,有一些改进的思路,整体其实有很大问题的,也欢迎大佬们指出来。
后期项目代码会放到github上开源,有需要的小伙伴也可以私信我

2022-05-03

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:14:27  更:2022-05-05 11:15:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:17:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码