首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

2.snail-job集群定时任务

  • 24-12-16 16:08
  • 3303
  • 9857
juejin.cn

前言

​ 上一节《1.snail-job初体验》中,已经运行了一个定时任务,初步了解snail-job的基本用法。本节,主要是针对集群定时任务,做进一步的了解。这里就包括任务管理页面中的每项配置作用,并对重要的配置项做代码测试。

本节目标

  • 采用JDK17以上实现客户端
  • 注解方式实现定时任务客户端
  • 记录日志到任务服务端
  • 任务管理页面中定时任务配置项详细解释
  • 对阻塞策略、超时时间、最大重试次数配置项进行测试理解

Maven依赖

JDK17及其以上的maven依赖

xml
代码解读
复制代码
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> <version>3.3.3version> dependency> <dependency> <groupId>com.aizudagroupId> <artifactId>snail-job-client-starterartifactId> <version>1.1.2version> dependency> <dependency> <groupId>com.aizudagroupId> <artifactId>snail-job-client-retry-coreartifactId> <version>1.1.2version> dependency> <dependency> <groupId>com.aizudagroupId> <artifactId>snail-job-client-job-coreartifactId> <version>1.1.2version> dependency> dependencies>

大概说明下snail-job依赖库的作用:

库名主要作用
snail-job-client-startersnail-job客户端启动时,和springboot框架相结合的初始框架代码
snail-job-client-retry-core实现重试任务的核心代码。
snail-job-client-job-core实现定时任务的核心代码

说明:

如果你的项目中不涉及重试任务,实际上不引入snail-job-client-retry-core的依赖也是可以的,不会影响到定时任务;反之亦然。

logback配置文件

在本节目标中,希望把日志写到服务端上。所以这里需要配置下logback-spring.xml文件:

xml
代码解读
复制代码
"1.0" encoding="UTF-8"?> <configuration> <property name="log.path" value="./logs"/> <property name="console.log.pattern" value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${console.log.pattern}pattern> <charset>utf-8charset> encoder> appender> <appender name="snailLogAppender" class="com.aizuda.snailjob.client.common.appender.SnailLogbackAppender"> appender> <root level="info"> <appender-ref ref="console" /> <appender-ref ref="file_info" /> <appender-ref ref="file_warn" /> <appender-ref ref="file_error" /> <appender-ref ref="snailLogAppender" /> root> configuration>

测试类

​ 由于在上一节中已经介绍过配置文件和启动类的注意事项了。这里补充说明一点,如果你的服务端ip和客户端ip不是同一台机器的话,建议在配置文件中指定一下客户端ip【snail-job.host=192.168.1.123】,否则取到的默认ip可能不对,从而造成服务端访问不到客户端的情况。测试类具体注解测试类代码如下:

java
代码解读
复制代码
@Slf4j @Component @JobExecutor(name = "testSnailJobWithAnnotation") public class TestSnailJobWithAnnotation { public ExecuteResult jobExecute(JobArgs jobArgs) { log.info("定时任务执行成功.参数值:{}", jobArgs); SnailJobLog.LOCAL.info("LOCAL日志.参数值:{}", jobArgs); SnailJobLog.REMOTE.info("REMOTE日志.参数值:{}", jobArgs); return ExecuteResult.success("测试注解方式的定时任务成功"); } }

说明:

  1. 默认执行的方法名是jobExecute,如果需要修改的话,则可以修改@JobExecutor的mothod属性。如:

​ @JobExecutor(name = "testSnailJobWithAnnotation", method="myJob")

  1. 执行器的名称在同一组下是不允许重复的。如果你另外一个定时任务类也叫testSnailJobWithAnnotation那么在客户端启动的时候就会报错:SnailJobClientException: 不允许executorName重复的

  2. 本测试代码中SnailJobLog.LOCAL.info和采用slf4j的log记录日志效果一样,都是在客户端记录日志;而SnailJobLog.REMOTE.info则是在服务端记录日志。

定时任务管理页面

对定时任务的任务管理和执行批次页面,进行了解。

image-20240919142353336

任务管理-新增/编辑定时任务

下面是该在服务器的任务管理页面中,添加我们上面的测试类了。在这里顺便解释下定时任务的配置项。

image-20240918152748854

任务名称

定时任务的一个名称,最好是看到这个名字,就知道这个定时是干嘛用的。

组名称

这个在上一节中已经有比较详细的描述。这里可以简单把组理解为项目或者应用。

状态

分为启用和禁用两种状态。禁用状态时,服务端不再调度该任务。并且只有禁用状态的任务才能被删除。

任务类型

image-20240918153653110

本文主要是讲述集群任务类型的,这里先不展开其他的任务类型。目前仅需知道集群任务类型,能保证服务端可以按照下面将要说到的路由策略,只命中一台客户端节点执行任务。至于其他的任务类型,将在后续文章中单独介绍。

执行器类型

image-20240918154230292

snail-job在支持java客户端的同时,还支持Python客户端。未来还可能支持GO语言的客户端。

执行器名称

image-20240918162822145

最常用的是自定义执行器,由于我们客户端采用注解的方式,所以这里的名字和用注解中的name值一致即可。不用像上一篇那样要写全路径类名了。方法参数中填写的内容,可以通过方法参数的JobArgs对象获得。除了这个最最常用的自定义执行器,snail-job还内置了几个执行器名称:

image-20240918163429795
执行器名称作用
Http执行器通过http请求调用一个接口的方式,定时执行任务。
CMD执行器定时执行window上的.bat文件
PowerShell执行器定时执行PowerShell 脚本文件,通常是.ps1文件
Shell执行器定时执行linux上的.sh文件

路由策略

就是服务端通过什么策略来路由到客户端。snail-job有如下路由策略:

image-20240918164720432
路由策略解释说明
最后一个客户端a、b、c三台集群的情况下,总是命中c这台机器
第一个客户端a、b、c三台集群的情况下,总是命中a这台机器
轮询客户端a、b、c三台集群的情况下,总是安装a、b、c这种每台命中一次的节奏周而复始
LRU客户端a、b、c三台集群的情况下,会命中最近最少使用的那台客户端。
随机客户端a、b、c三台集群的情况下,随机命中一台
一致性哈希客户端a、b、c三台集群的情况下,一致性哈希算法会稳定的调度其中一台机器。

阻塞策略

​ 阻塞策略这个是处理服务端到了该触发客户端任务A的时候,但是发现任务A还在运行。此时就需要一个策略来处理该情况。

image-20240920140948954

简单的说,就是服务端应该触发某个任务,发现该任务没结束呢,此时该咋办呢?那么由你来决定。你可以选择的处理方式有如下几种方式:

策略解释
丢弃你都没干完,我不干
覆盖你别干了,我来干
并行直接开干
恢复继续把失败的任务干完

这几个策略在本文后面的测试中,进行逐一测试验证

触发类型

服务端以哪种类型来触发客户端,包括如下可选类型:

image-20240919104835679
类型名说明
固定时间以一个固定时间间隔来触发客户端执行任务。
CRON表达式以Cron表达式设置的时间来触发客户端执行任务
工作流工作流这个会在后续文章单独介绍

时间间隔

会根据前面选择的触发类型不同而有所变化。

类型时间间隔
固定时间这里是间隔的秒数。如:600秒,10分钟触发一次
CRON表达式这里是一个cron表达式的触发。如:0 35 13 * * ?

cron表达式管理页面有很好的支持,可以通过页面进行配置。尤其是其中还有验证表达式是否正确的最近5次运行时间。

image-20240919110207514

超时时间(秒)

这里的超时时间,就是你对这个定时任务预估完成的时间。如果设置的过短,可能导致其实客户端任务已经返回运行成功了,但是在任务批次列表【后面讲述】中显示任务执行超时。

最大重试次数

首先说明,这里有几种情况会触发服务端重新调度客户端任务。

  • 网络超时
  • 客户端明确返回错误
  • 客户端出现异常

这里设置的次数,就是发生上面情况时,重试的最大次数。

特别说明:

任务超时是不会触发服务端重新调度客户端任务的。

重试间隔(秒)

在需要重新调度客户端任务时,两次重试的时间间隔。

描述

对该任务的详细描述。

任务管理-任务列表

image-20240920095546185

说明两个名词定义:

  • 任务项

    这个列表中的每一条记录叫任务项

  • 批次

    每个批次就是一次服务度对客户端的调度。而这个调度可能是一个或者多个任务。当然,针对本节讲述的集群定时任务来说,一个批次调度的是一个任务。而任务类型为:广播、 分片、 map、 mapreduce 的任务就会牵扯到多个任务。这个后续文章讲述。

任务管理-执行批次

执行批次页面可以通过两种方式进入:

  • 在任务管理-任务列表中,点击任务项后面操作中的批次按钮
  • 直接在菜单项中点击执行批次菜单项

两者的区别是,任务列表中点击某个任务项后面的批次按钮,则直接看到的该任务下的批次列表;而直接通过菜单项看到的是所有任务的批次列表。

进行测试

这里测试的目的包括:

  • 为了实现本节目标,验证日志记录到服务器上。
  • 为了深入理解阻塞策略、超时时间、最大重试次数配置项对定时任务的影响

验证注解方式定时任务

把我们最开始写的测试类,进行验证。

客户端代码

java
代码解读
复制代码
@Slf4j @Component @JobExecutor(name = "testSnailJobWithAnnotation") public class TestSnailJobWithAnnotation { public ExecuteResult jobExecute(JobArgs jobArgs) { log.info("定时任务执行成功.参数值:{}", jobArgs); SnailJobLog.LOCAL.info("LOCAL日志.参数值:{}", jobArgs); SnailJobLog.REMOTE.info("REMOTE日志.参数值:{}", jobArgs); return ExecuteResult.success("测试注解方式的定时任务成功"); } }

页面配置

配置项配置内容
任务名称注解定时任务
组名称service_plat
状态启用
任务类型集群
执行器类型java
执行器名称testSnailJobWithAnnotation
方法参数{"date":"2024-09-20"}
路由策略轮询
阻塞策略丢弃
触发类型固定时间
间隔时长60秒
超时时间(秒)60秒
最大重试次数3
重试间隔1秒

测试结果

  • 执行批次页面中任务处理成功

    image-20240920151024259

  • 日志中能看到记录到服务端的日志

    点击上图中某个批次后面的日志,可以看到日志的详情信息

    image-20240920151534130

    点击查看日志后

    image-20240920151753445

测试总结

  • 注解方式的任务通过@JobExecutor来实现
  • SnailJobLog.LOCAL.info和log.info作用基本等价,都是在客户端写日志信息
  • SnailJobLog.REMOTE.info可以把日志写到服务端

验证最大重试次数和间隔

在前面介绍管理页面的时候,已经介绍过什么情况下会重试,在这里再次回顾下:

  • 网络超时
  • 客户端明确返回错误
  • 客户端出现异常

那我们客户端代码随便来个被0除的异常即可。余下的两种情况可自行进行测试。

客户端代码

java
代码解读
复制代码
@Component public class TestRetryTimes extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { int i = 1/0; return ExecuteResult.success(); } }

这里还是用上一篇文章中推荐的继承虚基类方式来做定时任务。好处有:

  • idea能自动补充需要实现的接口类。省得记入参和返回参数。
  • 避免任务重名

页面关键配置

其他配置项和上面的验证注解方式定时任务配置一样

配置项配置内容
任务名称测试最大重试次数和间隔
执行器名称com.bjltd.test.TestRetryTimes
触发类型CRON表达式
间隔时长0 22 09 * * ?
最大重试次数4
重试间隔10秒

说明

  • 执行器名称要填写包全路径名。这个是和注解方式有很大区别。
  • 这里采用cron表达式,任务每天就激活一次。主要为了方便查看测试结果,也更贴合实际应用场景。

测试结果

  • 客户端的控台

    这里抽取关键打印信息:

    shell
    代码解读
    复制代码
    2024-09-23 09:22:10 [snail-netty-server-2] INFO c.a.s.c.job.core.client.JobEndPoint - 任务执行/调度失败执行重试. 重试次数:[1] 2024-09-23 09:22:20 [snail-netty-server-3] INFO c.a.s.c.job.core.client.JobEndPoint - 任务执行/调度失败执行重试. 重试次数:[2] 2024-09-23 09:22:31 [snail-netty-server-4] INFO c.a.s.c.job.core.client.JobEndPoint - 任务执行/调度失败执行重试. 重试次数:[3] 2024-09-23 09:22:41 [snail-netty-server-5] INFO c.a.s.c.job.core.client.JobEndPoint - 任务执行/调度失败执行重试. 重试次数:[4]
  • 任务管理页面查看日志

    任务管理页面->点任务名称为测试最大重试次数和间隔任务项后面的批次按钮。在执行批次列表中点批次后面的日志按钮。

    image-20240923132709284

    在执行批次详情页面中点击查看日志按钮

    image-20240923132853922

    在日志详情中可以看到本批次的详细情况

    image-20240923133124726

测试总结

  • 网络超时、客户端明确返回错误、客户端出现异常会触发重试

  • 最大重试次数可以设置重试多少次

  • 重试间隔可以设置每次重试之间间隔的时间

验证阻塞策略-丢弃

策略解释
丢弃你都没干完,我不干

触发阻塞的前提是:服务端应该触发某个任务,发现该任务没结束。结合前提,这里大体测试思路是:每分钟执行一次定时任务,而任务执行时间是5分钟。这样就会触发阻塞策略了。

客户端代码

java
代码解读
复制代码
@Component public class TestDiscardJob extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { // 休眠5分钟 ThreadUtil.sleep(5, TimeUnit.MINUTES); return ExecuteResult.success(); } }

页面配置

配置项配置内容
任务名称测试阻塞策略-丢弃
执行器名称com.bjltd.test.TestDiscardJob
阻塞策略丢弃
触发类型固定时间
间隔时长60秒
超时时间600秒

测试结果

image-20240923164010376

1527这个批次,状态会从运行中变为处理成功。执行时长也从空更新为最终的执行时长了。

测试总结

  • 丢弃策略会一直等待前一个任务做完后,才会创建新的批次去调用客户端运行任务
  • 在某种程度上解决了幂等性,但不是绝对的

验证阻塞策略-覆盖

策略解释
覆盖你别干了,我来干

新批次开始之前会尝试中断旧批次的线程,但是不一定能终止掉。这里可以理解成在新批次开始前,调用了一个旧批次任务线程池的shutDownNow方法

客户端代码

  • 无法中断的情况

    java
    代码解读
    复制代码
    @Slf4j @Component public class TestOverlayCanNotInterrupted extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { log.info("{}开始执行任务", Thread.currentThread().getName()); for(int i = 1; i <= 5; i++) { log.info("{}执行第{}次", Thread.currentThread().getName(), i); ThreadUtil.sleep(60, TimeUnit.SECONDS); } log.info("{}任务执行完成", Thread.currentThread().getName()); return ExecuteResult.success(); } }
  • 可以中断的情况

    java
    代码解读
    复制代码
    @Slf4j @Component public class TestOverlayCanInterrupted extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { log.info("{}开始执行任务", Thread.currentThread().getName()); int i = 1; while (!Thread.currentThread().isInterrupted()) { log.info("{}执行第{}次", Thread.currentThread().getName(), i); try { Thread.sleep(60000); }catch (InterruptedException e) { log.info("{}任务被中断", Thread.currentThread().getName()); Thread.currentThread().interrupt();; } i++; } log.info("{}任务执行完成", Thread.currentThread().getName()); return ExecuteResult.success(); } }

页面配置

  • 无法中断的配置

    配置项配置内容
    任务名称测试阻塞策略-覆盖-无法中断
    执行器名称com.bjltd.test.TestOverlayCanNotInterrupted
    阻塞策略覆盖
    触发类型固定时间
    间隔时长60秒
    超时时间600秒
  • 可以中断的配置

    配置项配置内容
    任务名称测试阻塞策略-覆盖-可中断
    执行器名称com.bjltd.test.TestOverlayCanInterrupted
    阻塞策略覆盖
    触发类型固定时间
    间隔时长60秒
    超时时间600秒

测试结果

  • 无法中断的测试结果

    客户端日志信息:

    shell
    代码解读
    复制代码
    2024-09-24 11:19:51 [snail-netty-server-1] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1716] 任务调度成功. 2024-09-24 11:19:51 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1开始执行任务 2024-09-24 11:19:51 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1执行第1次 2024-09-24 11:20:01 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[6] 2024-09-24 11:20:43 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1执行第2次 2024-09-24 11:20:43 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1执行第3次 2024-09-24 11:20:50 [snail-netty-server-3] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1717] 任务调度成功. 2024-09-24 11:20:50 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1开始执行任务 2024-09-24 11:20:50 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1执行第1次 2024-09-24 11:21:01 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[14] 2024-09-24 11:21:43 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1执行第2次 2024-09-24 11:21:43 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1执行第3次 2024-09-24 11:21:43 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1执行第4次 2024-09-24 11:21:50 [snail-netty-server-5] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1718] 任务调度成功. 2024-09-24 11:21:50 [snail-job-job-1,718-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,718-1开始执行任务 2024-09-24 11:21:50 [snail-job-job-1,718-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,718-1执行第1次 2024-09-24 11:22:01 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[22] 2024-09-24 11:22:43 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1执行第4次 2024-09-24 11:22:43 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1执行第5次 2024-09-24 11:22:43 [snail-job-job-1,718-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,718-1执行第2次 2024-09-24 11:22:43 [snail-job-job-1,718-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,718-1执行第3次 2024-09-24 11:22:50 [snail-netty-server-7] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1719] 任务调度成功. 2024-09-24 11:22:50 [snail-job-job-1,719-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,719-1开始执行任务 2024-09-24 11:22:50 [snail-job-job-1,719-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,719-1执行第1次 2024-09-24 11:23:01 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[30] 2024-09-24 11:23:43 [snail-job-job-1,719-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,719-1执行第2次 2024-09-24 11:23:43 [snail-job-job-1,719-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,719-1执行第3次 2024-09-24 11:23:43 [snail-job-job-1,717-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,717-1执行第5次 2024-09-24 11:23:43 [snail-job-job-1,716-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,716-1任务执行完成 2024-09-24 11:23:43 [snail-job-job-1,718-1] INFO c.b.t.TestOverlayCanNotInterrupted - snail-job-job-1,718-1执行第4次 2024-09-24 11:23:50 [snail-netty-server-9] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1720] 任务调度成功.

    从日志打印可以看出,1716这个批次并没有被真正中断,还是会在后台持续的工作。

    任务批次列表中的显示

    image-20240924113039147

  • 可以中断的测试结果

    客户端日志信息:

    shell
    代码解读
    复制代码
    2024-09-24 15:04:41 [snail-netty-server-1] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1935] 任务调度成功. 2024-09-24 15:04:41 [snail-job-job-1,935-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,935-1开始执行任务 2024-09-24 15:04:41 [snail-job-job-1,935-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,935-1执行第1次 2024-09-24 15:04:51 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[4] 2024-09-24 15:05:40 [snail-job-job-1,935-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,935-1任务被中断 2024-09-24 15:05:40 [snail-job-job-1,935-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,935-1任务执行完成 2024-09-24 15:05:41 [snail-netty-server-3] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1936] 任务调度成功. 2024-09-24 15:05:41 [snail-job-job-1,936-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,936-1开始执行任务 2024-09-24 15:05:41 [snail-job-job-1,936-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,936-1执行第1次 2024-09-24 15:05:52 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[12] 2024-09-24 15:06:40 [snail-job-job-1,936-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,936-1任务被中断 2024-09-24 15:06:40 [snail-job-job-1,936-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,936-1任务执行完成 2024-09-24 15:06:40 [snail-netty-server-5] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1937] 任务调度成功. 2024-09-24 15:06:40 [snail-job-job-1,937-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,937-1开始执行任务 2024-09-24 15:06:40 [snail-job-job-1,937-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,937-1执行第1次 2024-09-24 15:06:51 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[20] 2024-09-24 15:07:40 [snail-job-job-1,937-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,937-1任务被中断 2024-09-24 15:07:40 [snail-job-job-1,937-1] INFO c.b.test.TestOverlayCanInterrupted - snail-job-job-1,937-1任务执行完成

    从日志输出能看出来,每个批次的任务都会被后面的新批次任务给停止。

    任务批次列表中的显示

    image-20240924151408848

测试总结

  • 新批次任务会停止上个批次任务,但是不保证一定停止成功。
  • 如果想让任务拥有被中断的能力,那么需要在写任务代码时,自己处理。比如本例通用循环判断当前线程是不是被中断。如果你的任务本身不具备这种能力。基本相当于下面将要验证的并行效果一样了。

验证阻塞策略-并行

策略解释
并行直接开干

这个策略顾名思义,就是和上一个批次的任务可以同时执行。

客户端代码

java
代码解读
复制代码
@Slf4j @Component public class TestConcurrency extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { log.info("{}开始执行任务", Thread.currentThread().getName()); for(int i = 1; i <= 5; i++) { log.info("{}执行第{}次", Thread.currentThread().getName(), i); ThreadUtil.sleep(60, TimeUnit.SECONDS); } log.info("{}任务执行完成", Thread.currentThread().getName()); return ExecuteResult.success(); } }

页面配置

配置项配置内容
任务名称测试阻塞策略-覆盖-可中断
执行器名称com.bjltd.test.TestConcurrency
阻塞策略并行
触发类型固定时间
间隔时长60秒
超时时间600秒

测试结果

image-20240924155824922

测试总结

  • 这个在实际应用中,一定要谨慎使用。
  • 采用该策略一定要充分考虑幂等性问题。

验证阻塞策略-恢复

策略解释
恢复继续把失败的任务干完

该模式是用在任务类型是多个任务的情况下使用的,比如像Map这种很多任务的情景下,还有就是工作流。作用就是跑其中失败的任务。集群任务就一个任务项,执行完后批次状态就变了,连触发任务都不能了,所以千万别在集群模式下选该策略。这个恢复策略,在后续讲解中再进行介绍。

验证超时时间

超时时间的设置,目的是在定时任务到了这个阈值还没有执行完,那么就会调用批次任务线程池的shutDownNow方法。这个和上面说到的覆盖策略很相似。同样也都不能保证任务一定被停止。

客户端代码

java
代码解读
复制代码
@Slf4j @Component public class TestTimeout extends AbstractJobExecutor { @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { try { // 休眠3分钟 Thread.sleep(3*60*1000); }catch (InterruptedException e){ return ExecuteResult.failure(); } return ExecuteResult.success(); } }

页面配置

配置项配置内容
任务名称测试超时时间
执行器名称com.bjltd.test.TestTimeout
路由策略轮询
阻塞策略丢弃
触发类型固定时间
间隔时长60秒
超时时间30秒

测试结果

客户端日志信息:

shell
代码解读
复制代码
2024-09-24 16:53:40 [snail-netty-server-1] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1992] 任务调度成功. 2024-09-24 16:53:40 [snail-job-job-1,992-1] INFO com.bjltd.test.TestTimeout - snail-job-job-1,992-1开始执行任务 2024-09-24 16:53:50 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[7] 2024-09-24 16:54:10 [snail-job-job-1,992-1] INFO com.bjltd.test.TestTimeout - snail-job-job-1,992-1任务被中断 2024-09-24 16:54:40 [snail-netty-server-3] INFO c.a.s.c.job.core.client.JobEndPoint - 批次:[1993] 任务调度成功. 2024-09-24 16:54:40 [snail-job-job-1,993-1] INFO com.bjltd.test.TestTimeout - snail-job-job-1,993-1开始执行任务 2024-09-24 16:54:50 [nioEventLoopGroup-2-1] INFO c.a.s.c.c.l.report.ReportLogListener - Data report log successfully requestId:[15] 2024-09-24 16:55:10 [snail-job-job-1,993-1] INFO com.bjltd.test.TestTimeout - snail-job-job-1,993-1任务被中断

从客户端日志中可以看出来,任务从开始到任务被中断间隔30秒。

任务批次列表中显示

image-20240924165900683

测试总结

  • 超时时间是设置任务最大可以执行时长。到了这个时间就会停止任务。
  • 停止任务并不保证必然停止
  • 它是一个保底方案。避免因为各种意外而造成的长时间任务驻留。

总结

  • 会用注解和继承类两种方式,实现自己的客户端定时任务。

  • 通过在logback配置中加SnailLogbackAppender,能把日志写到服务端。

  • 阻塞策略是反正在该执行任务的时候,还有任务还在执行。可以选择的策略如下:

    策略解释
    丢弃你都没干完,我不干
    覆盖你别干了,我来干
    并行直接开干
    恢复继续把失败的任务干完
  • 超时时间是到了这个时间点,如果任务还没执行完,就调用该任务线程池的shutdownNow方法。

注:本文转载自juejin.cn的老马9527的文章"https://juejin.cn/post/7418074037392293914"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top