定时任务调度方案——Xxl-Job
定时任务调度方案
随着系统规模的发展,项目的组织结构以及架构越来越复杂,业务覆盖的范围越来越广,定时任务数量日益增多,任务也变得越来越复杂,尤其是为了满足在用户体量日历增大时,系统能够稳定运行,我们往往会扩充服务器做集群,无论是传统垂直项目还是如今主流的分布式。那么对定时任务的要求也逐渐变高,基于现在项目主流架构,定时任务需满足一下要求:
-
- 任务统一管理,提供图形化界面对任务进行配置和调度。
-
- 保证任务调度的幂等性(任务并发控制,同一个任务在同一时间只能允许一个执行)
-
- 任务弹性扩容,可根据繁忙情况动态增减服务器分摊压力,对大任务进行分片处理。
-
- 任务依赖问题,能够处理任务包含子任务的情况,前一个完成后触发子任务执行。
-
- 支持多类型的任务,支持Spring Bean、Shell等。
-
- 任务节点高可用,任务节点异常或者繁忙时能够转移到其他节点执行。
-
- 调度中心高可用,支持集群部署,避免出现单点故障。
-
- 执行状态监控,方便查看任务执行状态,异常情况告警,支持多渠道通知。
#. 发展史:
定时任务随着技术发展,从单线程调度到多线程调度,从单机部署到集群部署,从独立执行到多任务协同执行。
1. Thread
通过线程休眠实现,由JDK提供
private static int count = 0;public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {while (count < 8) {try {Thread.sleep(1000);System.out.printf("执行第:%d 次\n", ++count);} catch (InterruptedException e) {e.printStackTrace();}}}};new Thread(runnable).start();
}
2. 线程池
有延缓执行实现,由JDK提供
private static int count = 0;public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 8; i++) {ExecutorService executorService = Executors.newSingleThreadScheduledExecutor();Runnable runnable = new Runnable() {@Overridepublic void run() {++count;System.out.printf("执行从 %d 次\n", count);if (count > 7) {System.exit(0);}}};// 也可以使用 ScheduledExecutorService.scheduleexecutorService.awaitTermination(1L, TimeUnit.SECONDS);executorService.execute(runnable);}
}
3. Timer TimeTask
由JDK提供,多用于移动端(如安卓开发)
private static int count = 0;public static void main(String[] args) {TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.printf("执行第 %d 次\n", ++count);if (count > 7) {System.exit(0);}}};Timer timer = new Timer();timer.schedule(timerTask, 500, 500);
}
4. Schedule
由Spring提供, 配合@EnableScheduling 使用
@Component
public class SpringScheduleTest {private static int count;@Scheduled(cron = "0/1 * * * * ?")public void testSchedule() {System.out.printf("执行第 %d 次\n", ++count);}
}
cron 表达式:秒-分-时-日-月-周-年
5.quartz
有maven独立依赖,在SpringBoot2.0之后自带包
- 纯maven项目依赖
<!-- 核心包 --> <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version> </dependency><!-- 工具包 --> <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.3.0</version> </dependency>
- SpringBoot2.0及上依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId> </dependency>
- 测试类 Test.java
public class Test {public static void main(String[] args) throws SchedulerException, ParseException {Scheduler factory = StdSchedulerFactory.getDefaultScheduler();JobDataMap jobDataMap = new JobDataMap();jobDataMap.put("tips", "去你大爷的");JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class).withIdentity("testJob", "testJobGroup").setJobData(jobDataMap).build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity("testTrigger", "testTriggerGroup").withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).startNow().build();factory.scheduleJob(jobDetail, trigger);factory.start();} }
- 创建任务类 QuartzJob.java
public class QuartzJob implements Job {public static int count;@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();String tips = jobDataMap.getString("tips");System.out.printf("获取到参数:%s\n", tips);System.out.printf("执行第:%d 次\n", ++count);} }
6. Xxl-job
XXL-JOB 是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
详细内容介绍,请查看:文档地址
-
创建库,并创建表,sql文件在项目目录下:xxl-job-master/doc/db/tables_xxl_job.sql
注意:它的数据库名是 xxl_job, 如果不想创建新库,而是导入到现有的库中,需要进入sql文件中改名字。
-
运行项目:xxl-job-admin
-
项目结构如下:
-
修改mysql 连接配置如下:
-
-
运行起来后, 在浏览器访问:http://localhost:8080/xxl-job-admin
默认账号:admin 密码:123456
-
成功登录后进入调度中心
-
注册任务执行器,可以单独创建执行器服务,也可集成到现有项目服务中去
以下为新建SpringBoot 项目为示例- 创建SpringBoot 项目并添加依赖
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.1</version> </dependency>
- 在resources目录下创建application.properties文件(yaml文件也一样,如果有就不用创建了)
# 执行器所在的服务的运行端口, 非执行器端口 server.port=8081### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" # 注册地址, 这个地址其实就是部署或者运行完xxl-job-admin调度中心的浏览器访问地址 xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin### xxl-job, access token xxl.job.accessToken=default_token### xxl-job executor appname ### 执行器名称,需要配置到调度中心 xxl.job.executor.appname=xxl-job-executor ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null xxl.job.executor.address= ### xxl-job executor server-info xxl.job.executor.ip= # 这个端口是执行器端口, 不是这个项目server.port 端口,也不能一样,否则会出现端口占用等错误信息 # 也就是说,执行器项目部署或者运行起来会有两个端口,如果是用docker部署,注意两个端口都要映射到宿主机端口 xxl.job.executor.port=9999 ### xxl-job executor log-path xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler ### xxl-job executor log-retention-days xxl.job.executor.logretentiondays=30
- 创建配置类 XxlJobConfig.java
@Configuration public class XxlJobConfig {@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.accessToken}")private String accessToken;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.address}")private String address;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setAddress(address);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;} }
- 创建任务 (Job),注意不同版本写法会有些不一样
@Component public class SampleXxlJob {/*** 1、简单任务示例(Bean模式)*/@XxlJob("demoJobHandler")public void demoJobHandler() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");for (int i = 0; i < 5; i++) {XxlJobHelper.log("beat at:" + i);TimeUnit.SECONDS.sleep(2);}XxlJobHelper.handleSuccess("XXL-JOB:执行成功");} }
- 配置执行器
- 配置
- 成功
- 配置
- 配置任务并执行
-
配置任务
-
执行一次
-
查看日志
-
- 创建SpringBoot 项目并添加依赖
相关文章:
定时任务调度方案——Xxl-Job
定时任务调度方案 随着系统规模的发展,项目的组织结构以及架构越来越复杂,业务覆盖的范围越来越广,定时任务数量日益增多,任务也变得越来越复杂,尤其是为了满足在用户体量日历增大时,系统能够稳定运行&…...
操作系统引导
操作系统是一种程序,程序以数据的形式存放在硬盘中,而硬盘通常分为多个区,一个计算机中又有多个或多种外部设备。 操作系统引导指的是计算机利用CPU运行特定程序,通过程序识别硬盘,识别硬盘分区,识别硬盘分…...
[C#] 多线程单例子,分为阻塞型和分阻塞型, 在unity里的应用
在单例中使用多线程时,需要注意以下几点: 线程安全:在多线程环境下,单例对象可能被多个线程同时访问,因此需要确保单例的线程安全,避免出现数据竞争等问题。 对象创建:如果在单例对象的构造函数…...
使用MAT进行内存分析,并找到OOM问题
前言 在处理一次现场问题时,发现服务还在运行,但是出现假死情况,后通过分析GC日志以及使用MAT分析确定问题是内存溢出OutOfMemery(OOM);这里只记录MAT分析学习过程,最近工作忙,补记录。 GC日志分析 首先,如…...
初识Python
目录初识Python1.Python简介Python的优缺点Python的应用领域2.安装Python解释器Windows环境Linux环境macOS环境3.运行Python程序确认Python的版本编写Python源代码运行程序代码中的注释4.Python开发工具IDLE - 自带的集成开发工具IPython - 更好的交互式编程工具Sublime Text -…...
tmux终端复用软件
一、安装[rootpool-100-1-1-159 test]# yum install tmux [rootpool-100-1-1-159 test]# yum search tmux Repository extras is listed more than once in the configuration Last metadata expiration check: 0:33:52 ago on Fri 03 Mar 2023 09:10:34 AM CST.Name Exactly M…...
IO详解(文件,流对象,一些练习)
目录 文件 文件概念 文件的路径 路径有俩种表示风格 文件类型 如何区分文本文件还是二进制文件? java对文件的操作 File类中的一些方法 流对象 流对象的简单概念 java标准库的流对象 1.字节流,(操作二进制数据的) 2.字符流 (操作文本数据的) 流对象最核心的四个…...
SpringCloud全家桶— — 【1】eureka、ribbon、nacos、feign、gateway
SpringCloud全家桶— — 组件搭建 1 Eureka 1.1 Eureka-server 创建eureka-server的SpringBoot项目 ①导入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId…...
【线程安全篇】
线程安全之原子性问题 x ,在字节码文件中对应多个指令,多个线程在运行多个指令时,就存在原子性、可见性问题 赋值 多线程场景下,一个指令如果包含多个字节码指令,那么就不再是原子操作。因为赋值的同时,…...
错误:EfficientDet网络出现“No boxes to NMS“并且mAP:0.0的解决方案
近日,在使用谷歌新推出来的一个网络EfficientDet进行目标检测训练自己的数据集的时候,出现了如下错误: 其中项目开源地址是:https://github.com/toandaominh1997/EfficientDet.Pytorch 上面截图中的1和2代表我的类别名称。读者可…...
python的opencv操作记录13——区域生长及分水岭算法
文章目录图像区域基本算法——形态学运算腐蚀与膨胀开运算与闭运算opencv中的形态学运算距离计算——distanceTransform函数连通域连通的定义计算连通域——connectedComponents连通域实验基于区域的分割区域生长算法自定义一个最简单区域生长算法实现区域分割一般区域分割open…...
一文看懂网上下单的手机流量卡为什么归属都是随机的!
最近很多网上下单的小伙伴们心中似乎都有一个疑问。那就是网上很多手机卡、流量卡都不能自选号码和归属地,就算能自选号码,归属地也是随机的而且很多都不会跟你说具体的城市,这是为什么呢?莫非其中有什么不可告人的秘密吗?小伙伴…...
python Pytest生成alluer测试报告的完整教程
1.下载allure包到本地,解压 网上很多资料,这边不提供了 2.配置环境变量 将上面解压后bin文件的路径复制,添加到环境变量Path下 3.验证环境变量配置是否功 在cmd中输入allure,回车 。查看allure是否成功: 4.pyc…...
4-spring篇
ApplicationContext refresh的流程 12个步骤 prepareRefresh 这一步创建和准备了Environment对象,并赋值给了ApplicationContext的成员变量 要理解Environment对象的作用 obtainFreshBeanFactory ApplicationContext 里面有一个成员变量,Beanfactory b…...
提升 Web 应用程序的性能:如何使用 JavaScript 编写缓存服务
缓存是一种重要的优化技术,用于加速数据访问和降低服务器负载。缓存存储经常访问的数据,以便在需要时可以快速检索。在本文中,我们将探索如何使用简单的数据结构在 JavaScript 中编写缓存服务。 编码缓存服务的第一步是定义将用于访问缓存的…...
供应商绩效管理指南:挑战、考核指标与管理工具
管理和优化供应商绩效既关键又具有挑战性。要知道价格并不是一切,如果你的供应商在商定的价格范围内向你开具发票,但服务达不到标准或货物不合格,你也无法达到节约成本的目标。 供应商绩效管理可以深入了解供应商可能带来的风险,…...
干货文稿|详解深度半监督学习
分享嘉宾 | 范越文稿整理 | William嘉宾介绍Introduction to Semi-Supervised Learning传统机器学习中的主流学习方法分为监督学习,无监督学习和半监督学习。这里存在一个是问题是为什么需要做半监督学习?首先是希望减少标注成本,因为目前可以…...
信箱|邮箱系统
技术:Java、JSP等摘要:在经济全球化和信息技术飞速发展的今天,通过邮件收发进行信息传递已经成为主流。目前,基于B/S(Browser/Server)模式的MIS(Management information system)日益…...
JS数组拓展
1、Array.from Array.from 方法用于将两类对象转为真正的数组: 类似数组的对象,所谓类似数组的对象,本质特征只有一点,即必须有length属性。 因此,任何有length属性的对象,都可以通过Array.from方法转为数组 和 可遍历…...
一道很考验数据结构与算法的功底的笔试题:用JAVA设计一个缓存结构
我在上周的笔试中遇到了这样一道题目,觉得有难度而且很考验数据结构与算法的功底,因此Mark一下。 需求说明 设计并实现一个缓存数据结构: 该数据结构具有以下功能: get(key) 如果指定的key存在于缓存中,则返回与该键关联的值&am…...
(10)C#传智:命名空间、String/StringBuilder、指针、继承New(第10天)
内容开始多了,慢品慢尝才有滋味。 一、命名空间namespace 用于解决类重名问题,可以看作类的文件夹. 若代码与被使用的类,与当前的namespace相同,则不需要using. 若namespace不同时,调用的方法:…...
基于Jetson Tx2 Nx的Qt、树莓派等ARM64架构的Ptorch及torchvision的安装
前提 已经安装好了python、pip及最基本的依赖库 若未安装好点击python及pip安装请参考这篇博文 https://blog.csdn.net/m0_51683386/article/details/129320492?spm1001.2014.3001.5502 特别提醒 一定要先根据自己板子情况,找好python、torch、torchvision的安…...
MySQL存储引擎详解及对比和选择
什么是存储引擎? MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善…...
【推拉框-手风琴】vue3实现手风琴效果的组件
简言 在工作时有时会用到竖形手风琴效果的组件。 在此记录下实现代码和实现思路。 手风琴实现 结构搭建 搭建结构主要实现盒子间的排列效果。 用flex布局或者其他布局方式将内容在一行排列把每一项的内容和项头用盒子包裹, 内容就是这一项要展示的内容…...
滑动窗口最大值:单调队列
239. 滑动窗口最大值 难度困难2154收藏分享切换为英文接收动态反馈 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例…...
负载均衡算法
静态负载均衡 轮询 将请求按顺序轮流地分配到每个节点上,不关心每个节点实际的连接数和当前的系统负载。 优点:简单高效,易于水平扩展,每个节点满足字面意义上的均衡; 缺点:没有考虑机器的性能问题&…...
C语言数组二维数组
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量,比如 runoob0、runoob1、…、runoob99,而是…...
7年测试工程师,裸辞掉17K的工作,想跳槽找更好的,还是太高估自己了....
14年大学毕业后,在老师和朋友的推荐下,进了软件测试行业,这一干就是7年时间,当时大学本来就是计算机专业,虽然专业学的一塌糊涂,但是当年的软件测试属于新兴行业,人才缺口比较大,而且…...
企业为什么需要做APP安全评估?
近几年新型信息基础设施建设和移动互联网技术的不断发展,移动APP数量也呈现爆发式增长,进而APP自身的“脆弱性”也日益彰显,这对移动用户的个人信息及财产安全带来巨大威胁和挑战。在此背景下,国家出台了多部法律法规,…...
重回利润增长,涪陵榨菜为何能跑赢周期?
2022年消费市场持续低迷,疫情寒冬之下,不少食品快消企业均遭遇严重的业绩下滑,但一年里不断遭遇利空打击的“榨菜茅”涪陵榨菜,不仅安然躲过“酸菜劫”、走出“钠”争议,而且顺利将产品价格提起来,并在寒冬…...
老榕树建站软件/百度指数搜索榜
以一个马戏团要在某小镇表演而作的市场活动为例: 如果你在街上作一个牌子,写上“xxx马戏团将于x月x日在本镇上演大戏”,这就是在做“广告”。 如果你在马戏团里找一头大象,把这个牌子放在大象的背上,在大街上来回走动&…...
免费网站建设市场/怎么做推广让别人主动加我
计算机二级access题库答案在文末1.在Access数据库中,一个关系就是一个【 A】。A)二维表 B)记录C)字段 D)数据库 综合数据2. 设有部门和员工两个实体,每个员工只能属于一个部门,一个部门可以有多名员工,则部门与…...
flash 做网站教程/优化大师官网
集合框架(collections framework)首先要明确,集合代表了一组对象(和数组一样,但数组长度不能变,而集合能)。Java中的集合框架定义了一套规范,用来表示、操作集合,使具体操作与实现细节解耦。其实说白了,可以…...
保定建网站需要多少钱/全网网站推广
php中在做文件下载的时候,其中要加上这么一些header信息: 1 2 3 4 header("Content-type: application/octet-stream"); header("Accept-Ranges: bytes"); header("Accept-Length:".$fileSize); //请用Content-Length he…...
网站怎样做wap端/国内新闻最新消息十条
第1关:通信簿.csv文件进行查询 本关任务:编写函数cztxb,实现根据姓名对通信录.csv文件查询。输入查询的姓名,若文件中存在该人,显示其信息;当查询的姓名不存在时,显示“查无此人”。 #当前位置的sc文件夹下csv格式文件“通信簿”, #该文件每行记录一个姓名、住址、电话…...
郑州网站建设服务商/电商数据分析
http://www.2cto.com/kf/201501/374051.html 线程对象属于一次性消耗品,一般线程执行完run方法之后,线程就正常结束了,线程结束之后就报废了,不能再次start,只能新建一个线程对象。但有时run方法是永远不会结束的。例如…...