From c3f44b3c9053435ba1eea925dc4ce3737d2b1235 Mon Sep 17 00:00:00 2001 From: sladro Date: Wed, 11 Feb 2026 12:59:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B3=E6=BB=91=EF=BC=8C=E5=B9=B6=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 18 ++++++++++ .gitattributes | 31 ++++++++++++++++ pom.xml | 11 +++++- .../service/DataCollectorService.java | 35 +++---------------- .../service/DataProcessingService.java | 19 ++-------- 5 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..816038a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml,json,xml}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcce2b4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,31 @@ +* text=auto + +# Enforce UTF-8 text files in repository and normalized LF line endings. +*.java text eol=lf working-tree-encoding=UTF-8 +*.kt text eol=lf working-tree-encoding=UTF-8 +*.groovy text eol=lf working-tree-encoding=UTF-8 +*.xml text eol=lf working-tree-encoding=UTF-8 +*.properties text eol=lf working-tree-encoding=UTF-8 +*.yml text eol=lf working-tree-encoding=UTF-8 +*.yaml text eol=lf working-tree-encoding=UTF-8 +*.json text eol=lf working-tree-encoding=UTF-8 +*.sql text eol=lf working-tree-encoding=UTF-8 +*.sh text eol=lf working-tree-encoding=UTF-8 +*.md text eol=lf working-tree-encoding=UTF-8 + +# Windows scripts keep CRLF for direct execution. +*.bat text eol=crlf working-tree-encoding=UTF-8 +*.cmd text eol=crlf working-tree-encoding=UTF-8 +*.ps1 text eol=crlf working-tree-encoding=UTF-8 + +# Binary files must never be normalized. +*.jar binary +*.war binary +*.zip binary +*.gz binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.pdf binary diff --git a/pom.xml b/pom.xml index 972c68f..a0f2250 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ 1.0.1 UTF-8 + UTF-8 UTF-8 21 3.1.1 @@ -292,6 +293,14 @@ + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + ${project.build.resourcesEncoding} + + org.springframework.boot spring-boot-maven-plugin @@ -328,4 +337,4 @@ - \ No newline at end of file + diff --git a/qaup-collision/src/main/java/com/qaup/collision/datacollector/service/DataCollectorService.java b/qaup-collision/src/main/java/com/qaup/collision/datacollector/service/DataCollectorService.java index a3c57f4..11942cf 100644 --- a/qaup-collision/src/main/java/com/qaup/collision/datacollector/service/DataCollectorService.java +++ b/qaup-collision/src/main/java/com/qaup/collision/datacollector/service/DataCollectorService.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; @@ -85,10 +84,6 @@ public class DataCollectorService { * - 在多线程调度器下,若上游抖动/超时,fixedRate 会产生并发重入。 * - 这里用 AtomicBoolean 做最小侵入的“防重入”保护,不改变正常情况下的业务逻辑。 */ - private final AtomicBoolean aircraftCollectInProgress = new AtomicBoolean(false); - private final AtomicBoolean vehicleCollectInProgress = new AtomicBoolean(false); - private final AtomicBoolean unmannedCollectInProgress = new AtomicBoolean(false); - @Autowired private DataCollectorDao dataCollectorDao; @@ -539,18 +534,14 @@ public class DataCollectorService { return 6371000.0 * c; } - @Scheduled(fixedRateString = "${data.collector.interval}") + // Fixed-delay scheduling prevents overlap without dropping cycles. + @Scheduled(fixedDelayString = "${data.collector.interval}") public void collectAircraftData() { if (collectorDisabled) { return; } // 丢弃旧轮次:上一轮未完成时跳过,避免任务堆积 - if (!aircraftCollectInProgress.compareAndSet(false, true)) { - log.warn("航空器采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)"); - return; - } - try { List newAircrafts = dataCollectorDao.collectAircraftData(airportAircraftEndpoint, airportBaseUrl); if (newAircrafts.isEmpty()) { @@ -606,8 +597,6 @@ public class DataCollectorService { } catch (Exception e) { log.error("采集航空器数据异常", e); - } finally { - aircraftCollectInProgress.set(false); } } @@ -621,19 +610,13 @@ public class DataCollectorService { * - 数据采集后直接用于碰撞检测等实时计算 * - 不进行数据持久化 */ - @Scheduled(fixedRateString = "${data.collector.interval}") - @Async // 异步执行 + @Scheduled(fixedDelayString = "${data.collector.interval}") public void collectVehicleData() { if (collectorDisabled) { return; } // 丢弃旧轮次:上一轮未完成时跳过,避免 fixedRate + @Async 并发堆积 - if (!vehicleCollectInProgress.compareAndSet(false, true)) { - log.warn("机场车辆采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)"); - return; - } - try { List vehicles = dataCollectorDao.collectVehicleData(airportVehicleEndpoint, airportBaseUrl); if (vehicles.isEmpty()) { @@ -701,8 +684,6 @@ public class DataCollectorService { } catch (Exception e) { log.error("采集机场车辆数据异常", e); - } finally { - vehicleCollectInProgress.set(false); } } @@ -716,19 +697,13 @@ public class DataCollectorService { * - 包含missionContext任务信息,支持里程和路径点数据 * - 数据仅用于实时处理,不存储到数据库 */ - @Scheduled(fixedRateString = "${data.collector.vehicle-manager.http.poll-interval-ms:1000}") - @Async // 异步执行 + @Scheduled(fixedDelayString = "${data.collector.vehicle-manager.http.poll-interval-ms:1000}") public void collectUnmannedVehicleData() { if (collectorDisabled) { return; } // 丢弃旧轮次:上一轮未完成时跳过,避免“多车循环HTTP + fixedRate + @Async”堆积 - if (!unmannedCollectInProgress.compareAndSet(false, true)) { - log.warn("无人车状态采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)"); - return; - } - try { if (unmannedVehicleIds.isEmpty()) { // 启动时可能尚未刷新到列表,这里做一次快速拉取作为兜底 @@ -883,8 +858,6 @@ public class DataCollectorService { } catch (Exception e) { log.error("采集无人车数据异常", e); - } finally { - unmannedCollectInProgress.set(false); } } diff --git a/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java b/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java index 8b39a6e..1341a9f 100644 --- a/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java +++ b/qaup-collision/src/main/java/com/qaup/collision/dataprocessing/service/DataProcessingService.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import com.qaup.collision.datacollector.dao.DataCollectorDao; @@ -99,8 +98,6 @@ public class DataProcessingService { * 防止@Scheduled任务重入导致并发执行、消息风暴与数据库压力。 * 固定频率调度在任务执行时间超过间隔时可能出现并发重入。 */ - private final AtomicBoolean periodicProcessingInProgress = new AtomicBoolean(false); - /** * 设置活跃对象缓存的引用(由DataCollectorService调用) */ @@ -121,21 +118,13 @@ public class DataProcessingService { * 7. 执行违规检测 * 8. 保存无人车数据到数据库 */ - @Scheduled(fixedRateString = "${data.collector.detection.interval:1000}") + // Fixed-delay scheduling prevents overlap without dropping cycles. + @Scheduled(fixedDelayString = "${data.collector.detection.interval:1000}") @Transactional public void performPeriodicDataProcessing() { if (collectorDisabled) { return; } - - // 丢弃旧轮次:如果上一轮尚未完成,直接跳过本轮以保证实时性 - if (!periodicProcessingInProgress.compareAndSet(false, true)) { - log.warn("周期性数据处理上一轮尚未完成,跳过本轮以避免重入(保持实时性)"); - return; - } - - try { - if (activeMovingObjectsCache == null || activeMovingObjectsCache.isEmpty()) { log.debug("活跃对象缓存为空,仅处理航班通知/路由重试后返回"); // 航班通知与路由下发不依赖活跃对象列表,避免因为无移动对象而错过路由重试 @@ -171,10 +160,6 @@ public class DataProcessingService { saveUnmannedVehicleDataPeriodically(currentActiveObjects); log.info("周期性数据处理完成"); - - } finally { - periodicProcessingInProgress.set(false); - } } /**