1. 新增需求
在原行程甘特图基础上,新增地面时间甘特图,展示飞机在指定时间范围内的空闲时段(未执行航班的时间)。
输入数据结构:
{
"planeId": "PLANE_ID",
"origin": "HKG",
"destination": "NRT",
"departureTime": "2022-01-01T00:00:00Z",
"arrivalTime": "2022-01-01T05:00:00Z"
}
2. 系统架构更新
flowchart TD
A[前端] -->|HTTP请求| B(API网关)
B --> C[查询服务]
C --> D[(数据库)]
D --> C
C -->|JSON数据| E[甘特图渲染引擎]
E --> A
C --> F[地面时间计算模块] <!-- 新增模块 -->
3. 地面时间计算逻辑
3.1 计算规则
-
输入时间范围:
[start_time, end_time] -
步骤:
-
获取选定飞机在时间范围内的所有行程(按起飞时间排序)。
-
计算以下时段:
- 首段空闲:
start_time到 第一个行程的起飞时间。 - 中间空闲:相邻行程的 前一到达时间 到 后一起飞时间。
- 末段空闲:最后一个行程的到达时间 到
end_time。
- 首段空闲:
-
地点标识:空闲时段所在地点为前一航班的到达地(若为首段,则为第一个行程的出发地)。
-
3.2 示例
| 行程序列 | 空闲时段计算 | 地点 |
|---|---|---|
| 无行程 | 整个时间范围为空闲 | 基地 |
| 行程1: HKG→NRT (01:25-05:55) | 空闲1: 00:00-01:25(HKG) 空闲2: 05:55-08:39(NRT) |
4. 数据模型扩展
4.1 新增字段
在trips表中增加origin和destination字段以支持地点追踪:
ALTER TABLE trips
ADD COLUMN origin VARCHAR(3) NOT NULL, -- 机场IATA代码(如HKG)
ADD COLUMN destination VARCHAR(3) NOT NULL;
4.2 数据示例
| plane_id | origin | destination | departure (UTC) | arrival (UTC) |
|---|---|---|---|---|
| PlaneA | HKG | NRT | 2024-01-02 01:25:00 | 2024-01-02 05:55:00 |
5. 后端服务设计
5.1 API端点
- 原有端点:
GET /api/trips(获取行程数据) - 新增端点:
GET /api/ground-times(获取地面时间数据)
# Request
GET /api/ground-times?plane_ids=PlaneA,PlaneB&start=2024-01-02T00:00Z&end=2024-01-02T23:59Z
# Response
HTTP 200 OK
{
"PlaneA": [
{
"location": "HKG",
"start": "2024-01-02T00:00:00Z",
"end": "2024-01-02T01:25:00Z",
"duration_minutes": 85
},
{
"location": "NRT",
"start": "2024-01-02T05:55:00Z",
"end": "2024-01-02T08:39:00Z",
"duration_minutes": 164
}
]
}
5.2 计算逻辑实现
-
查询行程数据:
SELECT plane_id, origin, destination, departure, arrival FROM trips WHERE plane_id IN (:plane_ids) AND departure >= :start_time AND arrival <= :end_time ORDER BY plane_id, departure; -
后端计算地面时间(伪代码):
def calculate_ground_times(trips, start_time, end_time):
ground_periods = []
for plane_id, trips in group_by_plane(trips):
sorted_trips = sort_by_departure(trips)
prev_arrival = None
# 处理首段空闲
if sorted_trips[0].departure > start_time:
ground_periods.append({
"location": sorted_trips[0].origin,
"start": start_time,
"end": sorted_trips[0].departure
})
# 处理中间空闲
for i in range(1, len(sorted_trips)):
prev_trip = sorted_trips[i-1]
current_trip = sorted_trips[i]
if prev_trip.arrival < current_trip.departure:
ground_periods.append({
"location": prev_trip.destination,
"start": prev_trip.arrival,
"end": current_trip.departure
})
# 处理末段空闲
last_trip = sorted_trips[-1]
if last_trip.arrival < end_time:
ground_periods.append({
"location": last_trip.destination,
"start": last_trip.arrival,
"end": end_time
})
return ground_periods
6. 性能优化
6.1 数据库优化
-
索引优化:
CREATE INDEX idx_trips_plane_departure ON trips (plane_id, departure); -
分区策略:按
plane_id哈希分区,分散I/O压力。
6.2 计算层优化
- 并行计算:对每个飞机的行程独立计算地面时间,利用多线程/协程加速。
- 缓存结果:使用Redis缓存常见查询(如当天数据),设置TTL=1小时。
6.3 前端优化
- 按需渲染:仅渲染用户屏幕可见时间范围的地面时段。
- 数据压缩:使用二进制协议(如Protocol Buffers)传输数据。
-
7. 风险与应对
| 风险 | 应对措施 |
|---|---|
| 行程时间重叠 | 插入数据时校验departure > 前一航班的arrival。 |
| 跨时区显示错误 | 存储和传输时间均为UTC,前端本地化转换。 |
| 大规模数据计算延迟 | 预计算每日地面时间并存储结果。 |
8. 讨论点
-
数据实时性:若航班延误导致地面时间变化,如何快速更新?
- 方案:监听航班变更事件,触发地面时间重新计算。
-
地点模糊性:飞机在地面期间可能移动(如维修机库→跑道),是否需要更细粒度位置追踪?
- 方案:扩展
location字段为详细位置编码(需额外数据采集)。
- 方案:扩展
-
空档期利用率:是否需与其他系统(如维修系统)集成,自动分配任务?
-
附录:
-
Mermaid地面时间甘特图示例
gantt title Ground time of Plane A,B and C from 0000-2359 dateFormat MM-DD HH:mm axisFormat %H:%M todayMarker off section PlaneA HKG :01-01 21:00, 265min NRT :01-02 05:55, 164min TPE :01-02 12:29, 81min HKG :01-02 15:50, 600min section PlaneB HKG :01-02 04:30, 281min NGO :01-02 13:11, 263min HKG :01-02 21:34, 300min section PlaneC YVR :01-01 23:30, 150min HKG :01-02 14:30, 270min NRT :01-02 23:00, 150min-
性能测试建议:
- 模拟10,000架飞机,每机每日10条行程,测试查询响应时间。
- 对比带/不带缓存的吞吐量差异。
-