好吧又是被吐槽写了挫挫的代码的一天,虽然写的代码不太好,但是还是新学习了Quartz作业调度框架的使用,现做个笔记吧~
首先介绍下在做项目的需求:
使用flume读取日志文件,使用拦截器对日志文件的内容进行信息聚合后存储到es当中。在这个过程中,会存在因意外原因丢失数据的问题,而当部分数据丢失,会引起flume拦截器中有部分多余的信息堆积,长此以往会降低flume的处理速度。
针对这个问题,现设计的是使用Quartz实现一个定时任务,定时去判断拦截器中是否有数据堆积,并将堆积的数据删除。
二话不说,直接上代码~
首先是定义MyScheduler类
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.concurrent.TimeUnit;
public class MyScheduler {
public void go() throws Exception {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//获得要执行的对象
JobDetail snapJobDetail = JobBuilder.newJob(SnapJob.class).withIdentity("job1","group1").build();
JobDetail coverJobDetai = JobBuilder.newJob(CoverJob.class).withIdentity("job2","group2").build();
//定义触发器
Trigger trigger1 = TriggerBuilder.newTrigger().withIdentity("trigger1","triggerGroup1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(2)
.repeatForever()).build();
Trigger trigger2 = TriggerBuilder.newTrigger().withIdentity("trigger2","triggerGroup2")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(2)
.repeatForever()).build();
//将任务和Trigger放入scheduler
scheduler.scheduleJob(snapJobDetail,trigger1);
scheduler.scheduleJob(coverJobDetai,trigger2);
//启动
scheduler.start();
}
}
然后定义SnapJob类,CoverJob类同理
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
public class SnapJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Long time = new Date().getTime();
Iterator<Map.Entry<String,SnapBean>> it = MyInterceptor.snapMap.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,SnapBean> entry = it.next();
String startTime = entry.getValue().getStartTime();
try {
Long start = simpleDateFormat.parse(startTime.split("\\+")[0]).getTime();
if(time - start > 12000){
MyInterceptor.snapMap.remove(entry.getKey());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
而在MyInterceptor类中会有对应的Map定义,这里就不放代码啦~开启定时任务的代码如下(我是在flume拦截器初始化的时候开启的)
public void initialize() {
// TODO Auto-generated method stub
new Thread("cleaner"){
@Override
public void run(){
MyScheduler myScheduler = new MyScheduler();
try {
myScheduler.go();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
其实有个更加好的做法是不需要使用定时任务,直接将数据保存在Caffeine缓存中就行了,可以使用expireAfterWrite来设置数据在缓存中存留的时间,即:
Cache<String, SnapBean> snapCache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
嗯就先写到这儿吧~