平滑,并避免编码
This commit is contained in:
parent
7bb910892a
commit
c3f44b3c90
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -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
|
||||||
31
.gitattributes
vendored
Normal file
31
.gitattributes
vendored
Normal file
@ -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
|
||||||
9
pom.xml
9
pom.xml
@ -11,6 +11,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<qaup.version>1.0.1</qaup.version>
|
<qaup.version>1.0.1</qaup.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.build.resourcesEncoding>UTF-8</project.build.resourcesEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
@ -292,6 +293,14 @@
|
|||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>${project.build.resourcesEncoding}</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
|||||||
@ -33,7 +33,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.locationtech.jts.geom.GeometryFactory;
|
import org.locationtech.jts.geom.GeometryFactory;
|
||||||
import org.locationtech.jts.geom.Point;
|
import org.locationtech.jts.geom.Point;
|
||||||
@ -85,10 +84,6 @@ public class DataCollectorService {
|
|||||||
* - 在多线程调度器下,若上游抖动/超时,fixedRate 会产生并发重入。
|
* - 在多线程调度器下,若上游抖动/超时,fixedRate 会产生并发重入。
|
||||||
* - 这里用 AtomicBoolean 做最小侵入的“防重入”保护,不改变正常情况下的业务逻辑。
|
* - 这里用 AtomicBoolean 做最小侵入的“防重入”保护,不改变正常情况下的业务逻辑。
|
||||||
*/
|
*/
|
||||||
private final AtomicBoolean aircraftCollectInProgress = new AtomicBoolean(false);
|
|
||||||
private final AtomicBoolean vehicleCollectInProgress = new AtomicBoolean(false);
|
|
||||||
private final AtomicBoolean unmannedCollectInProgress = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataCollectorDao dataCollectorDao;
|
private DataCollectorDao dataCollectorDao;
|
||||||
|
|
||||||
@ -539,18 +534,14 @@ public class DataCollectorService {
|
|||||||
return 6371000.0 * c;
|
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() {
|
public void collectAircraftData() {
|
||||||
if (collectorDisabled) {
|
if (collectorDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 丢弃旧轮次:上一轮未完成时跳过,避免任务堆积
|
// 丢弃旧轮次:上一轮未完成时跳过,避免任务堆积
|
||||||
if (!aircraftCollectInProgress.compareAndSet(false, true)) {
|
|
||||||
log.warn("航空器采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<Aircraft> newAircrafts = dataCollectorDao.collectAircraftData(airportAircraftEndpoint, airportBaseUrl);
|
List<Aircraft> newAircrafts = dataCollectorDao.collectAircraftData(airportAircraftEndpoint, airportBaseUrl);
|
||||||
if (newAircrafts.isEmpty()) {
|
if (newAircrafts.isEmpty()) {
|
||||||
@ -606,8 +597,6 @@ public class DataCollectorService {
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("采集航空器数据异常", e);
|
log.error("采集航空器数据异常", e);
|
||||||
} finally {
|
|
||||||
aircraftCollectInProgress.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,19 +610,13 @@ public class DataCollectorService {
|
|||||||
* - 数据采集后直接用于碰撞检测等实时计算
|
* - 数据采集后直接用于碰撞检测等实时计算
|
||||||
* - 不进行数据持久化
|
* - 不进行数据持久化
|
||||||
*/
|
*/
|
||||||
@Scheduled(fixedRateString = "${data.collector.interval}")
|
@Scheduled(fixedDelayString = "${data.collector.interval}")
|
||||||
@Async // 异步执行
|
|
||||||
public void collectVehicleData() {
|
public void collectVehicleData() {
|
||||||
if (collectorDisabled) {
|
if (collectorDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 丢弃旧轮次:上一轮未完成时跳过,避免 fixedRate + @Async 并发堆积
|
// 丢弃旧轮次:上一轮未完成时跳过,避免 fixedRate + @Async 并发堆积
|
||||||
if (!vehicleCollectInProgress.compareAndSet(false, true)) {
|
|
||||||
log.warn("机场车辆采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<AirportVehicle> vehicles = dataCollectorDao.collectVehicleData(airportVehicleEndpoint, airportBaseUrl);
|
List<AirportVehicle> vehicles = dataCollectorDao.collectVehicleData(airportVehicleEndpoint, airportBaseUrl);
|
||||||
if (vehicles.isEmpty()) {
|
if (vehicles.isEmpty()) {
|
||||||
@ -701,8 +684,6 @@ public class DataCollectorService {
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("采集机场车辆数据异常", e);
|
log.error("采集机场车辆数据异常", e);
|
||||||
} finally {
|
|
||||||
vehicleCollectInProgress.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,19 +697,13 @@ public class DataCollectorService {
|
|||||||
* - 包含missionContext任务信息,支持里程和路径点数据
|
* - 包含missionContext任务信息,支持里程和路径点数据
|
||||||
* - 数据仅用于实时处理,不存储到数据库
|
* - 数据仅用于实时处理,不存储到数据库
|
||||||
*/
|
*/
|
||||||
@Scheduled(fixedRateString = "${data.collector.vehicle-manager.http.poll-interval-ms:1000}")
|
@Scheduled(fixedDelayString = "${data.collector.vehicle-manager.http.poll-interval-ms:1000}")
|
||||||
@Async // 异步执行
|
|
||||||
public void collectUnmannedVehicleData() {
|
public void collectUnmannedVehicleData() {
|
||||||
if (collectorDisabled) {
|
if (collectorDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 丢弃旧轮次:上一轮未完成时跳过,避免“多车循环HTTP + fixedRate + @Async”堆积
|
// 丢弃旧轮次:上一轮未完成时跳过,避免“多车循环HTTP + fixedRate + @Async”堆积
|
||||||
if (!unmannedCollectInProgress.compareAndSet(false, true)) {
|
|
||||||
log.warn("无人车状态采集上一轮尚未完成,跳过本轮以避免堆积(保持实时性)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (unmannedVehicleIds.isEmpty()) {
|
if (unmannedVehicleIds.isEmpty()) {
|
||||||
// 启动时可能尚未刷新到列表,这里做一次快速拉取作为兜底
|
// 启动时可能尚未刷新到列表,这里做一次快速拉取作为兜底
|
||||||
@ -883,8 +858,6 @@ public class DataCollectorService {
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("采集无人车数据异常", e);
|
log.error("采集无人车数据异常", e);
|
||||||
} finally {
|
|
||||||
unmannedCollectInProgress.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,6 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.qaup.collision.datacollector.dao.DataCollectorDao;
|
import com.qaup.collision.datacollector.dao.DataCollectorDao;
|
||||||
@ -99,8 +98,6 @@ public class DataProcessingService {
|
|||||||
* 防止@Scheduled任务重入导致并发执行、消息风暴与数据库压力。
|
* 防止@Scheduled任务重入导致并发执行、消息风暴与数据库压力。
|
||||||
* 固定频率调度在任务执行时间超过间隔时可能出现并发重入。
|
* 固定频率调度在任务执行时间超过间隔时可能出现并发重入。
|
||||||
*/
|
*/
|
||||||
private final AtomicBoolean periodicProcessingInProgress = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置活跃对象缓存的引用(由DataCollectorService调用)
|
* 设置活跃对象缓存的引用(由DataCollectorService调用)
|
||||||
*/
|
*/
|
||||||
@ -121,21 +118,13 @@ public class DataProcessingService {
|
|||||||
* 7. 执行违规检测
|
* 7. 执行违规检测
|
||||||
* 8. 保存无人车数据到数据库
|
* 8. 保存无人车数据到数据库
|
||||||
*/
|
*/
|
||||||
@Scheduled(fixedRateString = "${data.collector.detection.interval:1000}")
|
// Fixed-delay scheduling prevents overlap without dropping cycles.
|
||||||
|
@Scheduled(fixedDelayString = "${data.collector.detection.interval:1000}")
|
||||||
@Transactional
|
@Transactional
|
||||||
public void performPeriodicDataProcessing() {
|
public void performPeriodicDataProcessing() {
|
||||||
if (collectorDisabled) {
|
if (collectorDisabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 丢弃旧轮次:如果上一轮尚未完成,直接跳过本轮以保证实时性
|
|
||||||
if (!periodicProcessingInProgress.compareAndSet(false, true)) {
|
|
||||||
log.warn("周期性数据处理上一轮尚未完成,跳过本轮以避免重入(保持实时性)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (activeMovingObjectsCache == null || activeMovingObjectsCache.isEmpty()) {
|
if (activeMovingObjectsCache == null || activeMovingObjectsCache.isEmpty()) {
|
||||||
log.debug("活跃对象缓存为空,仅处理航班通知/路由重试后返回");
|
log.debug("活跃对象缓存为空,仅处理航班通知/路由重试后返回");
|
||||||
// 航班通知与路由下发不依赖活跃对象列表,避免因为无移动对象而错过路由重试
|
// 航班通知与路由下发不依赖活跃对象列表,避免因为无移动对象而错过路由重试
|
||||||
@ -171,10 +160,6 @@ public class DataProcessingService {
|
|||||||
saveUnmannedVehicleDataPeriodically(currentActiveObjects);
|
saveUnmannedVehicleDataPeriodically(currentActiveObjects);
|
||||||
|
|
||||||
log.info("周期性数据处理完成");
|
log.info("周期性数据处理完成");
|
||||||
|
|
||||||
} finally {
|
|
||||||
periodicProcessingInProgress.set(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user