序
本文主要研究一下PowerJob的CleanService
CleanService
@Slf4j
@Service
public class CleanService {
private final DFsService dFsService;
private final InstanceInfoRepository instanceInfoRepository;
private final WorkflowInstanceInfoRepository workflowInstanceInfoRepository;
private final WorkflowNodeInfoRepository workflowNodeInfoRepository;
private final LockService lockService;
private final int instanceInfoRetentionDay;
private final int localContainerRetentionDay;
private final int remoteContainerRetentionDay;
private static final int TEMPORARY_RETENTION_DAY = 3;
/**
* 每天凌晨3點定時清理
*/
private static final String CLEAN_TIME_EXPRESSION = "0 0 3 * * ?";
private static final String HISTORY_DELETE_LOCK = "history_delete_lock";
public CleanService(DFsService dFsService, InstanceInfoRepository instanceInfoRepository, WorkflowInstanceInfoRepository workflowInstanceInfoRepository,
WorkflowNodeInfoRepository workflowNodeInfoRepository, LockService lockService,
@Value("${oms.instanceinfo.retention}") int instanceInfoRetentionDay,
@Value("${oms.container.retention.local}") int localContainerRetentionDay,
@Value("${oms.container.retention.remote}") int remoteContainerRetentionDay) {
this.dFsService = dFsService;
this.instanceInfoRepository = instanceInfoRepository;
this.workflowInstanceInfoRepository = workflowInstanceInfoRepository;
this.workflowNodeInfoRepository = workflowNodeInfoRepository;
this.lockService = lockService;
this.instanceInfoRetentionDay = instanceInfoRetentionDay;
this.localContainerRetentionDay = localContainerRetentionDay;
this.remoteContainerRetentionDay = remoteContainerRetentionDay;
}
//......
}
CleanService提供了timingClean、cleanLocal方法
timingClean
@Async(PJThreadPool.TIMING_POOL)
@Scheduled(cron = CLEAN_TIME_EXPRESSION)
public void timingClean() {
// 釋放本地快取
WorkerClusterManagerService.cleanUp();
// 釋放磁碟空間
cleanLocal(OmsFileUtils.genLogDirPath(), instanceInfoRetentionDay);
cleanLocal(OmsFileUtils.genContainerJarPath(), localContainerRetentionDay);
cleanLocal(OmsFileUtils.genTemporaryPath(), TEMPORARY_RETENTION_DAY);
// 刪除資料庫歷史的資料
cleanByOneServer();
}
timingClean先執行WorkerClusterManagerService.cleanUp()釋放本地快取,之後透過cleanLocal釋放本地磁碟空間,最後執行cleanByOneServer刪除歷史資料
cleanLocal
@VisibleForTesting
public void cleanLocal(String path, int day) {
if (day < 0) {
log.info("[CleanService] won't clean up {} because of offset day <= 0.", path);
return;
}
Stopwatch stopwatch = Stopwatch.createStarted();
File dir = new File(path);
if (!dir.exists()) {
return;
}
File[] logFiles = dir.listFiles();
if (logFiles == null || logFiles.length == 0) {
return;
}
// 計算最大偏移量
long maxOffset = day * 24 * 60 * 60 * 1000L;
for (File f : logFiles) {
long offset = System.currentTimeMillis() - f.lastModified();
if (offset >= maxOffset) {
if (!f.delete()) {
log.warn("[CleanService] delete file({}) failed.", f.getName());
}else {
log.info("[CleanService] delete file({}) successfully.", f.getName());
}
}
}
log.info("[CleanService] clean {} successfully, using {}.", path, stopwatch.stop());
}
cleanLocal會刪除指定目錄中lastModified距離當前時間大於等於1天的檔案
cleanByOneServer
private void cleanByOneServer() {
// 只要第一個server搶到鎖其他server就會返回,所以鎖10分鐘應該足夠了
boolean lock = lockService.tryLock(HISTORY_DELETE_LOCK, 10 * 60 * 1000L);
if (!lock) {
log.info("[CleanService] clean job is already running, just return.");
return;
}
try {
// 刪除資料庫執行記錄
cleanInstanceLog();
cleanWorkflowInstanceLog();
// 刪除無用節點
cleanWorkflowNodeInfo();
// 刪除 GridFS 過期檔案
cleanRemote(Constants.LOG_BUCKET, instanceInfoRetentionDay);
cleanRemote(Constants.CONTAINER_BUCKET, remoteContainerRetentionDay);
} finally {
lockService.unlock(HISTORY_DELETE_LOCK);
}
}
cleanByOneServer先加鎖,然後執行cleanInstanceLog、cleanWorkflowInstanceLog、cleanWorkflowNodeInfo等
小結
PowerJob的CleanService提供了timingClean、cleanLocal方法,其中timingClean先執行WorkerClusterManagerService.cleanUp()釋放本地快取,之後透過cleanLocal釋放本地磁碟空間,最後執行cleanByOneServer刪除歷史資料;cleanLocal會刪除指定目錄中lastModified距離當前時間大於等於1天的檔案。