elasticjob监控

218 阅读3分钟

要实现的功能

job是否挂了?

当前时间减去上次执行时间的耗时,再减去间隔时间,仍然超过阈值(比如3分钟),就告警:某个job可能挂了。

job是否超时?

当前任务耗时超过间隔时间,就告警:某个job超时了。

如果是异步,就设置get的超时时间为间隔时间。如果超时,就告警:某个job超时了。

流程图

实现原理

job是否挂了?

有一个定时任务,扫描所有的job类。

在处理某个job的时候,比较时间:

  1. 先计算耗时

耗时=当前时间 - 上次执行时间

  1. 再和阈值比较

耗时 - 间隔时间 > 3m(阈值)


本质,其实是计算上次执行时间距离当前时间是否大于阈值(3m),

  1. 如果大于

就说明可能挂了

  1. 如果小于

说明job正常


上次执行时间,何时写入?

在job执行的时候,会写入当前执行时间到redis。

写入的作用?就是用于这个功能:监控job是否挂了。

也就是说,

  1. 何时写?

业务job执行的时候,写入当前执行时间。

  1. 何时读?

监控job执行的时候,会获取该业务job的上次执行时间(其实就是第一步的当前执行时间)。然后,比较时间差是否大于阈值(3m)。如果大于,就告警job可能挂了。

job是否超时?

业务job执行的时候,会计算当前任务的耗时,然后拿耗时和阈值(间隔时间)比较。如果大于阈值,就告警:当前业务job超时。

耗时怎么计算?

就是结束时间-开始时间。


如果是异步执行

就基于Future.get(间隔时间),来判断当前任务是否超时。

间隔时间,即超时时间。

本质其实就是,任务执行时间不能超过一个时间间隔周期,否则,就是超时了。

其他

其他的问题,都是细节问题。

监控job多久执行一次?

比如1m。

监控job怎么获取所有的业务job类?

写一个工具类,扫描某个包下面的所有的类。

比如,job类都在xxx.job包目录。

怎么获取间隔时间?

看代码

//获取业务job的间隔时间
			CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
			cronTriggerImpl.setCronExpression(cron);
			List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 3);
			Date date1 = dates.get(0);
			Date date2 = dates.get(1);
			long diffValue = date2.getTime()-date1.getTime();

上次执行时间存储在哪里?

时间的写和读,基于redis实现。

因为是分布式定时任务,是集群,是分片。

分片怎么区分?

key由什么组成?

  1. 有分片

JobDownException:业务job名字:分片的值

  1. 无分片

JobDownException:业务job名字

//循环处理每一个业务job类
public void monitorByAnnotation() {
			try {
				for (Class<?> cls : clazzs) {
					ElasticJobConf elasticJobConf = cls.getAnnotation(ElasticJobConf.class);
					String key = elasticJobConf.name();
					if (elasticJobConf.disabled()) {
						continue;
					}
					String keys[] = new String[elasticJobConf.shardingTotalCount()];
//判断是否有分片
					if (elasticJobConf.shardingTotalCount() > 1) { //有分片
						String itemParameters = elasticJobConf.shardingItemParameters();
						String[] split = itemParameters.split("[,]");
						for (int i = 0; i < split.length; i++) {
							keys[i] = elasticJobConf.name() + ":" + split[i];
						}
					} else { //没有分片
						keys[0] = elasticJobConf.name();
					}

					for (String str : keys) {
						excuteMethodByAnnotation(elasticJobConf.monitorPort(),elasticJobConf.cron(),str);
					}
				}
				} catch(Exception e){
					logger.error("monitorByAnnotation error", e);
				}
		}