xxl-job定时任务框架搭建与使用

pom文件配置需要特别注意的地方:

xxl-job框架自带的spring-boot版本为:1.5.21.RELEASE,与此匹配的spring-cloud版本为:Edgware.SR3,与spring-cloud版本匹配的spring-cloud-consul的版本为:1.3.3.RELEASE

执行器主要业务逻辑都在一个个jobHandler中,在jobHandler中完成所有的业务逻辑


xxl-job的系统组成:
主要就是分为调度中心和执行器,调度中心负责发起调度请求,将任务抽象成分散的jobHandler,交由执行器统一管理,本身不承担业务逻辑,执行器负责接收调度请求并执行对应的JobHandler中的业务逻辑,调度和任务两部分解耦,提高了系统整体稳定性和扩展性


xxl-job工作原理:

1.任务执行器根据配置的调度中心的地址,启动注册线程向调度中心的执行器管理发起自动注册,执行器管理保存注册执行器,后续根据注册信息给执行器下发任务。

2.执行器中的任务执行服务接收到任务后会将任务发送到待执行任务的队列中,队列中的任务会由执行线程依次获取并执行,执行线程会被维护到一个线程池中。

3.执行结果会被放到执行结果队列中,同时会把执行日志写入任务日志文件中,线程销毁任务结束,回调线程通知调度中心的监控运维模块,任务执行完毕。

4.日志查询:调度中心发送日志查询请求给任务执行器中的日志服务,然后查询任务日志文件实现。

* 问题:执行器HA,调度中心HA,添加任务调度时各个参数的含义,调度中心连数据库的原因。

调度中心连接数据库的原因

调度中心的任务管理:会将任务信息存到db中(xxl_job_info表是记录定时任务的db表),trigger_next_time(Long)字段,表示下一次触发的时间点,任务时间被修改 / 每一次任务触发后,trigger_next_time字段会更新

定时触发任务实现逻辑:使用时间轮实现

定时任务scheduleThread,不断从db中读取5秒内要执行的任务,立即触发 / 放到时间轮等待触发,并更新trigger_next_time

定时任务ringThread:时间轮实现到点触发任务,读取任务列表id---触发任务

当xxl-job应用本身(即:调度中心)集群部署(实现高可用HA)时,如何避免集群中的多个服务器同时调度任务?(即:分布式部署时,一个任务只执行一次)

通过悲观锁实现分布式锁(for update语句)

具体解释:即使是分布式部署,每个定时任务还是存储到db中,执行时从db拉取,所以只要保证db唯一即可

  • setAutoCommit(false)关闭隐式自动提交事务,启动事务
  • select lock for update(显式排他锁,其他事务无法进入&无法实现for update)
  • 读db任务信息 -> 拉任务到内存时间轮 -> 更新db任务信息
  • commit提交事务,同时会释放for update的排他锁(悲观锁)

Oracle中的悲观锁和乐观锁?

悲观锁:每次操作数据的时候都会上锁

实现方式:第一种select xxx for update ,操作时数据被锁定,只有commit或rollover才释放

第二种select xxx for update nowait,操作时数据被锁定,其他人访问时返回错误信息,内容资源正忙等

悲观锁可能造成死锁

乐观锁:操作数据时不会锁定,在更新的时候判断此期间数据有没有被更新,oracle默认使用乐观锁

实现方式:

第一种是操作数据前将数据copy到应用中,提交时进行对比

第二种是采用版本戳,在有乐观锁的数据库的table上建立一个column,number型,数据更新时版本加1,操作数据时记录当前版本,更新数据时比对当前版本和记录的版本是否一致

第三种是采用时间戳,同上,字段换成timestamp类型,比对的是最后一次更新的时间。

何时采用悲观锁和乐观锁?

系统并发量不大并且不允许脏读,使用悲观锁,并发量大、读多写少一般使用乐观锁。

* 问题:调度中心如何实现HA?(应该是具体应用场景具体分析吧)

任务执行器注册中心是如何实现的?

使用db表xxl_job_group记录下执行器的信息:执行器AppName、执行器名称title、执行器地址列表address_list(多地址逗号分隔)

如何实现任务执行器的路由?(有关执行器HA)

执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等(即:定时任务选择哪一个执行器执行)

任务执行器中的一些参数:

1.子任务ID:

任务详情页的任务ID,添加后即为当前任务的后续任务,后续任务执行的前提是上一个任务执行成功

2.路由策略:

执行器分布式部署时,选择执行器的策略

3.阻塞处理策略(调度过于密集,执行器来不及处理时的处理策略):

单机串行:调度请求进入执行器后进入队列,串行执行

丢弃后续调度:同一appname 只有一个执行器时,才能正常运作,因为任务是否在运行是在一个执行器上检查的,当调度请求进入执行器并且执行器存在正在运行的任务,则本次请求被丢弃并标记为失败

覆盖之前调度:同上,终止运行中的调度任务并清空队列,运行本次调度任务

4.任务超时时间:

如果任务执行的时间超过了设置的超时时间,那么任务会被打断,停止执行

5.失败重试次数:

任务失败时主动进行重试

6.报警邮件:

任务调度失败时邮件通知的地址,多个地址之间用逗号间隔

什么叫做任务自动发现?

任务绑定了执行器,任务触发调度时会自动发现注册成功的执行器

集群分布式调度一致性?

通过DB锁实现,调度中心通过抢占锁,之后执行调度操作

调度中心集群部署时的注意事项:

1.DB配置保持一致
2.登陆账号配置保持一致;
3.集群机器时钟保持一致(单机集群忽视)

执行器集群部署时的注意事项:

1.执行器回调地址(xxl.job.admin.addresses)需要保持一致;执行器根据该配置进行执行器自动注册等操作。 
2.同一个执行器集群内AppName(xxl.job.executor.appname)需要保持一致;调度中心根据该配置动态发现不同集群的在线执行器列表。

你可能感兴趣的:(java)