xxl-job 学习笔记

阅读更多

问题一:调度器(admin)和执行器(executor)之间如何互相通信?

admin公共spring-mvc提供了一个rest的接口给执行器调用(com.xxl.job.admin.controller.JobApiController#api)。

com.xxl.job.admin.controller.JobApiController#api方法作为执行器调用admin的统一入口,在该方法里面通过反射执行不同的操作(注册,删除注册,回调等),提供给执行器操作的api接口定义在com.xxl.job.core.biz.AdminBiz中。 其中回调主要是更新job的执行时间,执行是否成功等信息。

执行器(executor)启动之后提供给admin调用的入口是启动一个jetty server, 提供给admin操作的api定义在com.xxl.job.core.biz.ExecutorBiz中。

问题二:调度器(admin)和执行器(executor)如何知道彼此的ip端口?

执行器(executor)的配置文件中需要指定调度(admin)的地址

但是调度器(admin)并没有配置执行器的地址,而是通过执行器(executor)启动之后主动定时向调度器(admin)发送注册的心跳请求,请求里面包含了自己的appName和IP端口信息,然后admin将该信息保存到 XXL_JOB_QRTZ_TRIGGER_REGISTRY 表中

问题三:如果执行器有多个实例会怎样?

根据前面的问题二,假如有两个执行器a,b分别启动:

  • 执行器a启动并向admin注册,并告知自己的appName(假如是executor-sample)和ip端口(假如是192.168.15.1:9995)
  • admin保存执行器a的信息到XXL_JOB_QRTZ_TRIGGER_REGISTRY表(executor-sample:192.168.15.1:9995)
  • 执行器b启动并向admin注册,并告知自己的appName(同样是executor-sample)和ip端口(假如是192.168.15.2:9995)
  • admin保存执行器b的信息到XXL_JOB_QRTZ_TRIGGER_REGISTRY表(executor-sample:192.168.15.2:9995)
  • admin有一个后台线程(com.xxl.job.admin.core.thread.JobRegistryMonitorHelper)默认每隔30秒会去 XXL_JOB_QRTZ_TRIGGER_REGISTRY 表中读取有效的执行器注册记录(根据上次心跳时间),即executor-sample:192.168.15.1:9995和executor-sample:192.168.15.2:9995
  • 将appName:executor-sample最新的有效执行器列表保存到 XXL_JOB_QRTZ_TRIGGER_GROUP 表中,即insert一条记录appName:executor-sample, address_list为192.168.15.1:9995,192.168.15.2:9995

有上面的步骤可知,执行器启动的时候立即就会向调度中心admin注册,所以表到XXL_JOB_QRTZ_TRIGGER_REGISTRY中会立即产生注册的记录,但是由于后台任务JobRegistryMonitorHelper是每隔30刷新一次有效的执行器地址的,所以,从一台执行器启动并注册,到调度中心admin感知到该执行器的存在,会有一定时间的延迟。

经过以上的步骤,调度中心admin就可以维护起每个应用的有效的地址列表

那如果有一个定时任务需要执行的话,会分配到哪个执行器执行呢?

这就取决于我们在admin系统的任务管理页面配置任务的方式了,xxl-job支持多种路由策略(ExecutorRouteStrategyEnum):

  • 第一个(admin保存执行器地址的时候会按照字典排序,取第一个)
  • 最后一个(admin保存执行器地址的时候会按照字典排序,取最后一个)
  • 轮询
  • 随机
  • 一致性hash
  • 最不经常使用
  • 故障转移(会发循环发送实时的请求给每个执行器直到找到一台请求成功的机器为止)
  • 忙碌转移(和故障转移步骤类似,不同的是这里发送给执行器的请求是查询该机器是否空闲的请求) 等等。

xxl-job同样支持调度器(admin)集群,只要在执行器里面配置的时候配置多个admin的地址,用逗号分隔即可。 // TODO 如果启动了多个admin,xxl-job是如何避免重复调度任务呢?

问题四:xxl-job内部是如何调度任务的呢?

xxl-job内部添加-更新-删除任务是通过 XxlJobDynamicScheduler 的addJob, removeJob, updateJobCron来实现的, 其中比较有代表性的就是addJob了:

添加job的时候,xxl-job内部固定的制定job的bean类为RemoteHttpJobBean,也就是说不管这个任务的具体内容是什么,xxl-job都是通过RemoteHttpJobBean作为入口来实现的,RemoteHttpJobBean里面通过当前执行的任务的jobKey得到jobId(jobKey的name其实就是jobId)从而实现动态的调用具体的任务。

你可能感兴趣的:(xxl-job)