1.导入jar包
2.开启自动配置
package cn.indusec.sd.management.device;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* @author tong
* @date 2019/4/1
* @desc
*/
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@EnableDiscoveryClient
@EnableEurekaClient
@EnableJpaRepositories(basePackages = "cn.indusec.sd.api.repository.mysql")
@EntityScan(basePackages = "cn.indusec.sd.domain.mysql")
@ComponentScan(basePackages = {"cn.indusec.sd.api.service.mysql", "cn.indusec.sd.api.service.mongo", "cn.indusec.sd.security", "cn.indusec.sd.management.device"})
@EnableScheduling
@ServletComponentScan
@EnableMongoRepositories(basePackages = "cn.indusec.sd.api.repository.mongo")
public class DeviceManagementApplication {
public static void main(String[] args) {
SpringApplication.run(DeviceManagementApplication.class, args);
}
}
3.定时任务
package cn.indusec.sd.management.device.config;
import cn.indusec.sd.SystemInfo;
import cn.indusec.sd.api.service.mongo.DeviceLogService;
import cn.indusec.sd.api.service.mysql.OperateLogService;
import cn.indusec.sd.api.service.mysql.RuntimeLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* @author tong
* @date 2019/4/18
* @desc
*/
@Service
@Slf4j
public class SchedulerTask {
@Autowired
OperateLogService operateLogService;
@Autowired
RuntimeLogService runtimeLogService;
@Autowired
DeviceLogService deviceLogService;
@Value("${log.timed-delete.before-day}")
private int beforeDay;
@Value("${log.storage-capacity.rate}")
private double storageRate;
@Value("${log.storage-capacity.delete-day}")
private int deleteDay;
@Value("${log.storage-capacity.delete-rate}")
private double deleteRate;
/**
* 每天定时删除多少天以前的日志
*/
@Scheduled(cron = "0 0 0 * * ?")
public void clearLogTaskByTime() throws Exception{
log.info("日志清除定时任务开始执行");
Date time = getDate(new Date(), -beforeDay);
operateLogService.deleteByTime(time);
runtimeLogService.deleteByTime(time);
deviceLogService.deleteByTime(time);
log.info("日志清除定时任务执行完成");
}
/**
* 每天定时查看存储率是否达到设定的值,达到则删除部分日志
*/
@Scheduled(cron = "0 0 1 * * ?")
public void clearLogTaskByStorageCapacity() throws Exception{
log.info("检查日志存储率定时任务开始执行");
//存储率达到百分百之多少,删除离现在最远的多少天的日志
double mysqlCap = operateLogService.getMysqlCap();
double mongodbCap = deviceLogService.getMongodbCap();
double total = SystemInfo.getDeskUsage().getTotal();
log.info("服务器容量{}M", total);
if ((mysqlCap + mongodbCap) / total * 100 > storageRate) {
log.info("达到存储率上限,开始删除日志");
double newMysqlCap = deleteLog(deleteDay);
//(日志删除前容量-日志删除后容量)/日志删除前容量 例如:清除一次容量降低5%以下,继续清除,直到降低到5%以下
int i = 0;
while ((mysqlCap + mongodbCap - newMysqlCap) / (mysqlCap + mongodbCap) * 100 < deleteRate) {
if (i > 30) {
break; //最多删除30天日志,避免死循环,所有日志都被删除
}
log.info("日志清除容量未达到删除率,第{}次", ++i);
newMysqlCap = deleteLog(1); //每次删除一天的日志继续算清除率
}
}
log.info("检查日志存储率定时任务执行完成");
}
private double deleteLog(int day) throws Exception{
Date firstTimeLog = operateLogService.findFirstTimeLog();
if (firstTimeLog != null) {
Date time = getDate(firstTimeLog, day);
operateLogService.deleteByTime(time);
}
firstTimeLog = runtimeLogService.findFirstTimeLog();
if (firstTimeLog != null) {
Date time = getDate(firstTimeLog, day);
runtimeLogService.deleteByTime(time);
}
firstTimeLog = deviceLogService.findFirstTimeLog();
if (firstTimeLog != null) {
Date time = getDate(firstTimeLog, day);
deviceLogService.deleteByTime(time);
}
double mysqlCap = operateLogService.getMysqlCap();
double mongodbCap = deviceLogService.getMongodbCap();
return mysqlCap + mongodbCap;
}
private Date getDate(Date oldDate, int num) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(oldDate);
calendar.add(Calendar.DATE, num);
Date date = calendar.getTime();
String day = sdf.format(date);
Date time = sdf.parse(day);
return time;
}
}
application.yml
#日志定时删除配置
log:
timed-delete: #定时删除多少天以前的日志
before-day: 365
storage-capacity: #存储率达到百分百之多少, 删除最早的多少天的数据
rate: 90 #百分之多少
delete-day: 30 #删除最早的多少天的数据
delete-rate: 5 #触发定时删除时,删除数据的删除率,百分之多少,公式:(日志删除前容量-日志删除后容量)/日志删除前容量
#如不需要检查删除delete-day天后数据的删除率,此值设置为0即可
4.异常退出,释放资源
package cn.indusec.sd.management.device.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.Calendar;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author tong
* @date 2019/4/18
* @desc
*/
@Configuration
@Slf4j
public class SchedulerTaskConfigure implements SchedulingConfigurer {
private final AtomicInteger atomicInteger = new AtomicInteger(0);
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(buildExecutor());
}
/**
* 构建CSP定时任务的线程池
* @return
*/
private ScheduledThreadPoolExecutor buildExecutor(){
ScheduledThreadPoolExecutor poolExecutor = new ScheduledThreadPoolExecutor(12);
poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
poolExecutor.setThreadFactory(r->{
Thread thread = new Thread(Thread.currentThread().getThreadGroup(), r, "CSP scheduler-"+atomicInteger.getAndIncrement());
thread.setUncaughtExceptionHandler((t,e)->log.error("error while schedule thread "+t.getName(),e.getCause()));
return thread;
});
/**
* jvm退出时关闭线程池
*/
Runtime.getRuntime().addShutdownHook(new Thread(()->{
if( ! poolExecutor.isShutdown()){
log.info("we will shutdown CSP scheduler pool at :"+ Calendar.getInstance());
poolExecutor.shutdownNow();
}
}));
return poolExecutor;
}
}