Files
2026-07-27 18:28:21 +08:00

41 KiB
Raw Permalink Blame History

项目架构说明

1. 项目概述

ECAP_Server 是一个面向 Mode A/C/S、ADS-B 与相关设备数据的数据接入、解析、存储、转发和地图显示组合系统。后端以 C++ 可执行程序运行,接入 TCP、串口、文件、DLL 和共享内存等数据源,将报文交给 SSR 协议模块解析,并通过 HTTP、WebSocket 和数据转发服务对外提供结果。前端提供 Leaflet 二维地图与 Cesium 三维地图,共用飞机、轨迹、基站和子数据源业务状态。

当前源码可确认的主要运行平台是 Windows;构建脚本也保留 Linux 分支。最终产物包括:

  • ecap_server 后端可执行程序;
  • dll_source 等动态数据源组件;
  • Vite 生产构建生成的静态前端;
  • 本地影像、Terrarium 地形和 GLB 模型资源。

最核心的子系统是:

  1. 数据源和数据转发协程;
  2. SSR/ADS-B/CPR 协议解析与飞机状态;
  3. Drogon HTTP/WebSocket 服务;
  4. Leaflet/Cesium 地图渲染;
  5. 地形解码、LOS 通视分析和 Worker 调度。

关键入口:

  • psc_main()
    • module/Local_Server_main.cpp:56-175
  • Global::Global()
    • module/Local_Server/server/Global.cpp:58-145
  • App
    • third_party/eacp_webapp/src/App.tsx:36-293

2. 技术栈

层级 技术 用途 项目封装位置 关键源码
语言 C++20、TypeScript/TSX、JavaScript 后端、算法、前端 modulethird_party/SSRthird_party/eacp_webapp/src CMakeLists.txt, package.json
构建 CMake、自定义 _create/_depend/_attach_* 后端目标和依赖装配 third_party/build_inframain.cmake main.cmake
后端 Web Drogon/Trantor HTTP、WebSocket、静态 UI module/Local_Server/server Global::init_web_server()
并发 standalone Asio 1.38、C++ 协程、线程池 网络循环、数据处理、文件 I/O io_coro.*Ucoro_Drogon_Glue.h Coro::start(), ASIO_VERSION
协议 SSR 自有 Mode A/C/S、ADS-B、CPR 实现 报文解析、位置和距离算法 third_party/SSR/SSR parse_mode_s_bin(), CPR
数据格式 Psc JSON 配置、接口、业务序列化 Config.h、各模块 toJson/fromJson Config::fromJson()
存储 SQLiteCpp、文件 飞机/轨迹数据和配置 Database.*、配置文件 database_server()
前端 React 18、Ant Design、Vite 6 SPA、设置和业务面板 third_party/eacp_webapp package.json
二维地图 Leaflet 1.9 二维地图、飞机和轨迹 Leaflet_Map.tsxAircraft.tsx Leaflet_Map
三维地图 CesiumJS 1.143 地球、模型、轨迹、地形和相机 src/Map/Cesium_* Cesium_Map
地形 Terrarium PNG、CustomHeightmapTerrainProvider 本地高程地形 Terrarium_Terrain_* Terrarium_Terrain_Provider
浏览器并发 Web Worker、固定 Worker 池 PNG 解码和 LOS Worker_Pool.tsLos_Worker.ts Worker_Pool
日志 Core 日志封装 后端运行和协议日志 third_party/CPP_CoreGlobal.cpp Global::Global()
测试 GoogleTest、TypeScript、ESLint、Vite build 后端单测与前端静态验证 SSR 测试、前端 scripts CPR_TEST.cpp, package.json
部署 Drogon 静态资源、Cesium runtime copy 后端托管生产 UI vite.config.jsserver.cpp cesiumAssetsPlugin()

3. 仓库目录结构

目录 职责 类型与关系
module/Local_Server 主服务、配置、数据源、数据转发、飞机 VTO、HTTP/WebSocket 项目核心源码,依赖 SSR、Core、Drogon、Asio
module/dll_source 可由主服务加载的数据源 DLL 独立构建目标,主程序构建依赖它
module/mlat_sourcemodule/Radarcape_Core MLAT 和设备相关能力 由主服务按配置调用
third_party/SSR Mode A/C/S、ADS-B、CPR 算法和状态对象 深度集成的第三方/项目内算法库
third_party/CPP_Core 日志、网络、协程、JSON 等基础能力 多模块基础依赖
third_party/eacp_webapp React、Leaflet、Cesium 前端及模型 生产构建由后端静态托管
third_party/build_infra CMake 封装、工具链和依赖装配 顶层构建基础设施
config 源配置模板 构建后复制到目标目录
data 运行数据和数据库 后端运行期资源
arch_doc 架构和技术难点文档 本文档输出目录

构建输出、node_modules、IDE 缓存和生成文件不属于架构源码;它们只在验证生产资源和实际运行配置时使用。

4. 构建与启动结构

顶层 CMake 先加载构建基础设施、Core 和 SSR,再装配 ECAP 目标。ecap_server 关联整个 Local_Server 源目录、SSR、Drogon、SQLiteCpp、zlib 和 libarchive,并在构建后复制配置。

flowchart LR
    CMake[CMakeLists.txt] --> Infra[build_infra]
    CMake --> Core[CPP_Core]
    CMake --> SSR[SSR interface target]
    CMake --> Main[main.cmake]
    Main --> Server[ecap_server]
    Main --> DLL[dll_source]
    SSR --> Core
    Server --> SSR
    Server --> Drogon[Drogon]
    Server --> SQLite[SQLiteCpp]
    Server --> Archive[zlib/libarchive]
    Server --> DLL
    Vite[Vite build] --> WebRoot[wwwroot]
    WebRoot --> Server

证据:

后端启动顺序是:

  1. main() 进入 psc_main()
  2. 创建 Global,加载配置和模块;
  3. 初始化 Drogon 路由;
  4. 启动 Web 服务线程;
  5. 启动 Coro 的 Asio 网络线程和数据处理线程池;
  6. 主循环清理超时飞机并维持设备状态;
  7. 退出时先停协程和设备,再销毁全局对象。

开发模式由 Vite 代理后端 /api/map/tiles/ws;生产模式由 Drogon 提供 Vite 输出及 /ui/cesium/ui/model 静态资源。

5. 总体架构

flowchart LR
    Input[TCP/串口/文件/DLL/共享内存] --> Source[Data_Source]
    Source --> Parse[Data_Source_Handler]
    Parse --> SSR[SSR/ADS-B/CPR]
    SSR --> Aircraft[Aircraft_Info/轨迹]
    Parse --> Feed[Data_Feed]
    Aircraft --> DB[DataBase]
    DB --> WS[Aircraft WebSocket]
    Config[Config JSON] --> Source
    Config --> HTTP[Drogon HTTP]
    Tiles[本地影像/地形] --> HTTP
    HTTP --> Frontend[React 业务状态]
    WS --> Frontend
    Frontend --> Leaflet[Leaflet 2D]
    Frontend --> Cesium[Cesium 3D]
    Tiles --> Terrain[Terrarium Worker]
    Terrain --> Cesium
    Frontend --> LOS[LOS Worker Pool]
    LOS --> Cesium

依赖方向以数据接入、协议域对象、服务接口、前端业务模型、渲染适配器为主。Leaflet 和 Cesium 不应成为后端业务对象的依赖;统一飞机模型不运行时导入 Cesium。Cesium 专属坐标、Entity、Worker 和相机状态停留在三维适配层。

6. 核心模块说明

6.1 程序和全局运行时

职责

创建全局配置、服务、设备和数据源对象,控制后端启动与退出。

核心类型和函数

名称 类型 职责 生命周期 源码
psc_main() 函数 后端主流程 进程全生命周期 psc_main()
Global 单例类 配置和主要模块所有者 主流程创建、退出销毁 Global
Global::init_web_server() 函数 注册路由并启动 Web 配置 Global 初始化期 init_web_server()

输入是配置文件和运行参数,输出是持续运行的服务与模块集合。异常处理包含顶层退出路径和日志;部分初始化失败会阻止 init_ok

6.2 配置系统

职责

以一个 JSON 配置对象管理数据源、地图资源、二维/三维视图、Cesium 画质和模型元数据。

名称 类型 职责 生命周期 源码
Map_Tile_Config 结构体 瓦片目录、布局、Y 轴、投影和层级 配置生命周期 Map_Tile_Config
Map_View_Config 结构体 2D/3D 图层、层级和相机 配置生命周期 Map_View_Config
Cesium_Graphics_Config 结构体 画质、地形、日照和 LOS 配置生命周期 Cesium_Graphics_Config
Map_Model_Config 结构体 飞机、基站、设备、轨迹点模型 配置生命周期 Map_Model_Config
Config::fromJson/toJson 函数 单一配置解析和序列化 启动加载、接口保存 fromJson(), toJson()

地图接口只公开前端所需元数据,不公开本机目录。配置更新由后端接口写回同一配置对象和文件。

6.3 数据源与数据转发

职责

抽象不同输入介质,读取原始数据,在线程池解析,再向数据库、飞机状态和数据转发模块发布。

名称 类型 职责 生命周期 源码
Data_Source 基类 输入源、状态和显示配置 配置创建到停用/退出 Data_Source
Data_Source_Handler 基类 切包、解析、业务分发 随 Data Source Data_Source_Handler
Data_Feed 基类 向 TCP/UDP 等客户端转发 配置创建到退出 Data_Feed
Coro 单例类 Asio 网络循环和处理线程池 服务运行期 Coro

异步模型见第 10 节。主要失败路径包括输入断开、协议切包失败、解析异常和输出连接失败。With_Loop_Coro 状态机负责打开、循环和关闭。

6.4 SSR、ADS-B、CPR 和飞机状态

职责

解析 Mode S 报文,维护每架飞机的消息、空中/地面轨迹和派生属性;CPR 负责位置解码、球面距离和无线电视距范围。

名称 类型 职责 生命周期 源码
Data_Source_Interface 接口 SSR 对宿主数据源的最小依赖 随数据源 Data_Source_Interface
parse_mode_s_bin() 函数 Mode S 主解析入口 每条报文 parse_mode_s_bin()
Aircraft_Info 飞机状态和轨迹所有者 ICAO 出现到超时删除 Aircraft_Info
CPR::surface_position() 函数 基于参考站的地面 CPR 解码 地面位置报文 surface_position()
CPR::in_radio_line_of_sight_range() 函数 球面距离与理论视距过滤 位置候选校验 in_radio_line_of_sight_range()

Data_Source_Handler 将数据源中的基站位置和空中/地面约束传入 SSR,而不是让 SSR 反向依赖服务配置。

6.5 数据库与实时接口

职责

提供飞机/轨迹查询,并维护按 WebSocket 连接隔离的版本和轨迹订阅状态。

名称 类型 职责 生命周期 源码
Aircraft_Stream_Client_State 连接状态 保存各数据源版本和订阅 WebSocket 连接期 Aircraft_Stream_Client_State
aircraft_stream_source_update_json() 函数 构造单数据源增量 每次推送 aircraft_stream_source_update_json()
get_visible_aircraft_snapshot() 函数 点数和基站范围过滤 查询/推送时 get_visible_aircraft_snapshot()
register_aircraft_stream_ws() 函数 注册流和周期推送 服务生命周期 register_aircraft_stream_ws()

前端按 ICAO 返回 change_version 和轨迹位置,后端只发送变化、删除和被监控轨迹。全部监控与手动 ICAO 集合是不同状态。

6.6 HTTP、瓦片与资源配置

职责

按有序目录查找影像和地形瓦片,通过异步文件读取返回 GET/HEAD、缓存头和条件响应,同时提供公开资源元数据。

名称 类型 职责 生命周期 源码
Tile_Path_Resolver 按布局和目录优先级定位文件 服务生命周期 Tile_Path_Resolver
Tile_Source 查找、状态、读取和响应元数据 服务生命周期 Tile_Source
register_tile_handler() 函数 GET/HEAD、304、404 和回调桥接 路由注册期 register_tile_handler()
Global::init_tiles() 函数 创建影像、Google 影像、地形源 服务初始化期 init_tiles()

多目录严格按列表顺序查询,第一个普通文件获胜;不扫描全目录、不预加载瓦片。文件查找、status、打开和读取整体通过 to_drogon() 运行在专用 Asio 执行器,再回到 Drogon 事件循环完成一次回调。

6.7 前端统一业务状态

职责

Data_Source 保存子数据源、基站、飞机集合、2D/3D 显示配置和监控模式;Aircraft_Model 保存与渲染框架无关的飞机/轨迹状态。

名称 类型 职责 生命周期 源码
Data_Source 单数据源前端状态所有者 配置加载到页面卸载 Data_Source
Aircraft_Model 统一飞机位置、姿态、属性和轨迹 飞机出现到删除 Aircraft_Model
Aircraft_Stream_Client WebSocket 重连、订阅和增量应用 SPA 生命周期 Aircraft_Stream_Client

Leaflet 的 Aircraft 包装统一模型,Cesium 直接读取同一对象。Cesium 依赖只存在于三维适配器。

6.8 Leaflet 二维渲染

职责

维持原有二维地图、瓦片层、飞机图标、轨迹线和右键交互。

核心入口是 Leaflet_MapAircraft。二维对象由 Data_Source.aircraftMap 中的同一飞机实例驱动;轨迹监控状态来自共享数据源状态。

6.9 Cesium 三维渲染

职责

创建/销毁 Viewer,增量映射数据源、飞机、轨迹、基站和设备,接入影像、地形、模型、相机、LOS 与交互。

核心入口:

飞机使用 Model Entity,轨迹线使用 Polyline Entity,普通轨迹点使用 PointPrimitiveCollection,选中特殊点才使用模型 Entity。基站底座是地形到设备高度的世界空间模型;设备位于顶部,承担选择和完整信息。基站纵向比例由真实架设高度确定,横向显示大小通过模型节点变换控制。

6.10 地形、LOS 与相机

名称 类型 职责 生命周期 源码
Terrarium_Terrain_Provider 适配器 Cesium Heightmap Provider 和缓存 Viewer 生命周期 Terrarium_Terrain_Provider
Terrarium_Terrain_Worker Worker fetch、PNG 解码、RGB 转高度 Provider 生命周期 decode_terrarium_png()
Worker_Pool 调度器 固定并行度和 FIFO 任务 Cesium 生命周期 Worker_Pool
Los_Worker Worker ECEF 视线和地形采样 LOS Pool 生命周期 calculate_los()
Cesium_Camera_Control 控制器 地表、地心轨道、自由观察 Viewer 生命周期 Cesium_Camera_Control

7. 核心业务对象关系

classDiagram
    class Data_Source {
        Base_Station base_station
        Map aircraftMap
        Set manual_track_icao_set
        bool monitor_all_aircraft_mode
        map2d
        map3d
    }
    class Aircraft {
        Aircraft_Model data_model
        LeafletMarker marker
        TrackPath track
    }
    class Aircraft_Model {
        id
        longitude
        latitude
        altitude
        orientation
        trackPoints
    }
    class Cesium_Aircraft_Record {
        Model Entity
        Polyline Entity
        PointPrimitive records
        LOS Entity
    }
    class Base_Station {
        position
        range
        maxAircraft
    }
    class Cesium_Base_Record {
        Base world model
        Device Entity
        Range polylines
    }
    Data_Source *-- Base_Station
    Data_Source *-- Aircraft
    Aircraft *-- Aircraft_Model
    Aircraft_Model --> Cesium_Aircraft_Record
    Base_Station --> Cesium_Base_Record

业务主体是 Data_Source、飞机和基站状态;Cesium Entity、Primitive 和 Leaflet Layer 只是显示对象。一个飞机对应一个统一模型,同时可映射为 Leaflet Marker/Polyline 和 Cesium Model/Polyline/PointPrimitive。设备 Entity 是三维中可点击的基站业务入口,底部基站模型只表现物理支撑,不重复持有业务状态。

创建和销毁关系:

  • WebSocket 增量创建或删除 Data_Source.aircraftMap 中的飞机;
  • Leaflet 和 Cesium 按当前页面适配这些对象;
  • Cesium 用 key 到 record 的 Map 复用 Entity
  • 数据源或飞机删除时,渲染适配器同步删除关联轨迹、LOS 和模型;
  • Viewer 卸载时统一销毁 Worker、监听器、定时器和 Cesium 资源。

8. 运行时生命周期

sequenceDiagram
    participant Main as psc_main
    participant Global
    participant Coro
    participant Source as Data_Source
    participant SSR
    participant DB
    participant WS
    participant React
    participant Map as Leaflet/Cesium
    Main->>Global: 创建并加载配置
    Global->>DB: 注册 HTTP/WS
    Main->>Coro: start()
    Coro->>Source: 启动输入协程
    Source->>SSR: parse_mode_s_bin
    SSR-->>DB: 更新飞机/轨迹
    DB-->>WS: 版本增量
    WS-->>React: source delta
    React->>Map: 请求增量同步
    alt 进入 3D
        React->>Map: lazy import + load_map
        Map->>Map: 创建 Viewer/Worker/Provider
    else 离开 3D
        React->>Map: on_un_mount
        Map->>Map: 清理 Viewer/Worker/监听器
    end
    Main->>Coro: stop()
    Main->>Global: destroy()

/map3d 使用动态导入,未进入三维页面时不会执行 Viewer 初始化。WebGL 预检查失败会禁用三维入口并返回二维页面。对应源码:

9. 数据流

实时数据流

输入字节
→ Data_Source 异步读取
→ process_data 线程池切包/解析
→ SSR Aircraft_Info 和轨迹
→ DataBase 可见性过滤和版本比较
→ /ws/aircraft_stream 增量
→ Data_Source.aircraftMap
→ Leaflet/Cesium 渲染记录
→ 屏幕

WebSocket 消息是 JSON;前端保留每架飞机版本和最后轨迹大小。业务状态在前端对象中原地增量更新,Cesium 对象按 ID 复用,不在每次消息后重建 Viewer。

用户交互流

点击飞机/设备/轨迹点
→ Cesium/Leaflet picking
→ 找到 Data_Source 或 Aircraft_Model
→ 更新 active_aircraft/监控状态
→ 显示信息、轨迹或相机行为

基站范围辅助几何设置为忽略 picking,设备 Entity 才绑定完整基站信息。相关代码见 create_base_station_record()

地形与通视分析流

基站设备位置 + 飞机位置
→ LOS generation/request ID
→ Worker Pool
→ ECEF 直线采样
→ Terrarium 瓦片 fetch/cache/decode
→ 净空和首次遮挡结果
→ 丢弃过期 generation
→ 更新飞机 LOS 状态和连线

LOS Worker 接收普通数字结构,不传递 Cesium Viewer 或类实例。高度缓存位于各 Worker 内,返回结果会检查当前 generation,避免旧位置覆盖新位置。

配置更新流

设置表单临时值
→ HTTP PUT/POST
→ Global 中单一配置对象
→ config.json
→ 前端事件通知
→ 当前渲染器应用

地图资源接口只返回 URL、层级、投影、Y 轴和编码。模型上传由后端保存并更新模型 URL 和内置尺寸/初始角度配置。

10. 并发、异步和调度模型

flowchart TB
    Main[主线程/进程控制] --> Asio[Asio io_context 单网络线程]
    Asio --> Pool[process_data 线程池]
    Drogon[Drogon/Trantor 事件循环] --> TilePool[Ucoro Asio 专用线程]
    Browser[浏览器主线程] --> CesiumWorkers[Cesium 内置 Workers]
    Browser --> TerrainWorker[Terrarium Decode Worker]
    Browser --> LosPool[LOS Worker Pool]
    WS[WebSocket 事件] --> Browser
    Browser --> RAF[Cesium requestRender/postRender]

后端:

  • Coro::start() 创建一个 io_context 运行线程和按硬件并发度计算的 process_data 线程池;
  • 数据源在 io_context 读取,随后切换到 process_data 解析,再返回网络执行器;
  • 无等待模式使用每个数据源自己的 strand 串行化解析;
  • 瓦片 HTTP 桥接使用独立 Asio 线程池,整个文件系统查找和读取不在 Drogon 网络线程执行;
  • co_await 只表达挂起点,实际线程由当前 executor 决定。

浏览器:

  • React、WebSocket 消息处理、Cesium API 调用和 UI 在主线程;
  • Terrarium PNG 解码在独立 Worker
  • LOS 使用有上限的 Worker 池,Promise 只是调用和结果接口;
  • Cesium 自身还会使用其 runtime Workers
  • sync_data_sources() 先生成任务,再以最多 10 项或约 8 ms 的片段消费;
  • requestRenderMode 降低静止场景持续渲染成本;
  • Worker Pool 队列当前没有最大长度和任务取消,旧结果由实体 generation 淘汰。

关键证据:

11. Cesium 渲染架构

Viewer 在组件挂载后创建,在卸载时销毁。生产构建通过 CESIUM_BASE_URL=/ui/cesium/ 加载 Workers、Assets、ThirdParty 和 Widgets;模型来自 /ui/model

渲染对象选择:

业务对象 Cesium 对象 更新方式
飞机 Model Entity + Label ID Map 增量更新
轨迹线 Polyline Entity 更新位置数组
普通轨迹点 PointPrimitiveCollection 按轨迹序号增量增加/裁剪
选中/特殊轨迹点 Model Entity 只为特殊状态创建
基站底座 Model Entity 地形底部、世界空间高度
设备 Model Entity + Label 顶部位置、可点击
探测范围 预创建 Polyline Entity 集合 更新位置和 show
LOS Polyline/状态显示 Worker 结果更新

sync_data_sources() 会遍历当前启用数据源和飞机,这是已确认的全量发现阶段;已有记录由 Map 复用,重任务由分片队列消费。是否在目标规模下仍有长任务,需要 Chrome Performance 验证。

地形 Provider 使用 Web Mercator、配置层级和 XYZ/TMS 规则。2D 页面不加载 Cesium3D 页面根据设置启用 Terrarium。关闭地形或卸载 Viewer 时会销毁 Provider 和 Worker。

基站/设备当前空间语义:

  • 地形采样值是基站模型底部;
  • 配置设备高度是设备模型位置;
  • 基站模型纵向比例由两者高度差与模型原始高度计算;
  • “基站显示大小”只调整横向尺寸,不破坏顶部高度;
  • 设备可按子数据源选择固定屏幕尺寸或普通世界尺寸;
  • 完整基站信息绑定到设备,底座忽略 picking。

实现见 sync_base_station()create_base_station_record()base_station_heights()

12. 真正有难度的技术点

多执行器数据源协程

难度等级:
所属模块: Local_Server 数据源
解决的问题: 网络读取不能被协议解析阻塞,同时单数据源消息顺序必须稳定。
为什么困难: 同一逻辑跨 io_context、线程池和 strand,退出时还要等待未完成任务。
当前实现: 输入协程读取后切到 process_data;等待模式直接 co_await,无等待模式向 strand 投递;再回网络 executor。
关键算法或状态机: With_Loop_Coro 的打开、循环、关闭状态。
数据流: 输入字节 → 切包 → SSR → Feed/DB。
线程与异步边界: Data_Source::loop_coro()
性能成本: executor 切换、任务排队和 JSON/协议解析。
边界条件: 数据源断开、退出、处理速度落后。
失败方式: 顺序破坏、停止等待、线程池积压。
现有风险: 队列长度没有统一可观测指标。
可改进方向: 增加每源队列深度、耗时和丢弃策略指标。

WebSocket 版本增量与轨迹订阅

难度等级:
所属模块: Database、前端 Data_Source
解决的问题: 避免周期发送全部飞机和全部轨迹。
为什么困难: 每个连接、数据源、ICAO 都有版本和轨迹游标;还需区分全部监控和手动监控。
当前实现: 连接状态保存版本,前端订阅回传版本和轨迹大小,后端生成变化与删除。
关键算法或状态机: 连接状态 + per-source delta。
数据流: Snapshot → version compare → delta → apply/delete。
线程与异步边界: Drogon 事件循环和浏览器 WebSocket。
关键源码: Database.cppAircraft_Stream_Client
性能成本: 周期快照、版本 Map 比较和 JSON 序列化。
边界条件: 重连、飞机删除、监控模式切换。
失败方式: 版本失配造成漏更新或重复轨迹。
现有风险: 后端持锁遍历并发送连接,需要压力测试。
可改进方向: 锁内只构造待发送项,锁外发送;增加队列和消息尺寸指标。

Terrarium 地形与 LOS Worker

难度等级:
所属模块: Cesium 地形、LOS
解决的问题: 在不阻塞 UI 的情况下解码 PNG 高程并计算基站到飞机的地形通视。
为什么困难: 涉及 Web Mercator、XYZ/TMS、ECEF、地球曲率、异步瓦片、缓存和过期结果。
当前实现: Terrain Worker 解码 HeightmapLOS Worker 自行 fetch/cache/decode 并沿 ECEF 线采样。
关键算法或状态机: Terrarium R*256+G+B/256-32768generation 淘汰旧结果。
数据流: 普通数字协议 → Worker → Float32Array/LOS 结果。
线程与异步边界: 主线程只调度,解码和 LOS 在 Worker。
关键源码: Terrarium_Terrain_WorkerLos_Worker
性能成本: 网络请求、PNG 解码、每 Worker 独立缓存和采样次数。
边界条件: 404、缺少 OffscreenCanvas、层级上限、卸载。
失败方式: 队列积压、缓存重复、旧 LOS 覆盖新位置。
现有风险: Worker Pool 队列无硬上限。
可改进方向: 按飞机合并待处理任务并增加队列背压。

更多难点详见 项目技术难点说明

13. 性能架构

热点 状态 源码证据 验证方法
sync_data_sources() 遍历全部当前对象 已确认存在,但对象记录复用且任务分片 sync_data_sources() Chrome Performance,记录单次任务数和耗时
飞机 Entity 每次重建 已确认正常更新路径不存在;Map 复用记录 sync_aircraft() 统计 Entity add/remove
普通轨迹点全部使用 GLB 已确认不存在;使用 PointPrimitive create_aircraft_record() Cesium Inspector、Primitive 数量
React 消息导致 Viewer 重建 已确认正常增量消息不会重建 Viewer request_sync_data_sources() React Profiler
WebSocket 全量飞机 已确认已改为版本增量 aircraft_stream_source_update_json() 抓取消息尺寸和 change_list
LOS 对所有飞机无条件执行 需要结合运行配置和监控模式采样验证 update_aircraft_occlusion() Worker 任务计数/秒
地形 PNG 主线程解码 已确认不存在于 Provider/LOS 路径 Terrarium_Terrain_Worker Performance 主线程长任务
Worker 队列无界 已确认 Worker_Pool.run() 暴露 queue length 和等待时间
瓦片文件读取阻塞 Drogon 线程 已确认不存在;整体投递专用 Asio register_tile_handler() 并发 HTTP 延迟和线程采样
瓦片读取明显串行 源码推断:专用池大小为 1,需要压力测试确认影响 Ucoro_Drogon_Glue 32/64 并发瓦片吞吐
后端 WebSocket 锁内发送 已确认调用位置,实际阻塞程度待验证 push_aircraft_stream_updates() 慢客户端压力测试和锁等待
每帧高成本回调 未发现每帧地形解码或全量同步;性能面板 postRender 仍需 Profile postRender 注册 Performance flame chart

当前项目重点核查项:

核查项 状态
进入三维模式完整调用链 已确认
sync_data_sources() 全量发现 已确认存在,后续分片
飞机、基站、轨迹和模型重复创建 正常更新路径已确认不存在;边界重连需运行验证
高频位置按实体合并最新状态 WebSocket 版本增量已确认;Cesium generation 会替换待同步批次
分片队列生产超过消费 generation 替换旧批次;LOS 队列仍可能积压
离开三维后的清理 已确认有显式清理
LOS 是否对所有飞机执行 需运行配置和任务计数确认
高程采样线程 已确认在自定义 Worker
Promise 是否等同多线程 已确认没有混淆;真正并行来自 Worker
Worker 池并行和旧任务 固定并行和 generation 已确认;无队列上限
Entity/Primitive 选择 已确认普通轨迹点采用 PointPrimitive
基站与设备信息所有权 已确认设备承担交互,基站底座是显示对象
屏幕尺寸和世界尺寸 基站世界高度;设备可选固定屏幕尺寸
React 导致 Cesium 重建 正常消息路径已确认不会
每帧分配/全量遍历 未发现 LOS/地形全量每帧执行,仍需 Performance 确认

14. 配置与扩展点

  • 配置来源:config/config.json,由 Config::fromJson() 加载并由 toJson() 保存。
  • 业务配置:数据源协议、基站位置、点数限制、CPR 约束、理论范围过滤。
  • 显示配置:2D/3D 分层样式、瓦片源、相机、Cesium 画质、地形、LOS、日照和模型。
  • 新设备类型:扩展 Data_Source 子类和工厂注册,并提供 JSON 配置。
  • 新地图图层:扩展 Map_Resources_Config/map/resources 公开元数据,再在 2D/3D 适配器接入。
  • 新数据源:实现 Data_Source 的打开、读取、关闭协程,复用 Data_Source_Handler
  • 新算法:优先放在 SSR 或独立算法模块,通过小接口接入,避免渲染层反向依赖。
  • 新相机模式:扩展 Camera_Control_ModeCesium_Camera_Control.set_mode(),必须实现输入恢复和 destroy()
  • 新 Worker 任务:定义纯数据协议,通过 Worker_Pool 调度,明确缓存、过期和退出语义。

前端配置入口:

15. 架构风险

等级 风险 影响 证据 建议验证方式
LOS Worker Pool 队列无上限、不能取消执行中任务 飞机多且更新快时任务积压和无效请求 Worker_Pool.run() 记录 queue length、等待时间、旧结果比例
WebSocket 周期推送在全局客户端锁内构造并发送 慢连接可能扩大锁持有时间 push_aircraft_stream_updates() 多慢客户端压力测试
中高 三维同步仍有全量发现阶段 目标数增大后主线程扫描成本增长 sync_data_sources() 1k/10k 目标 Performance
中高 LOS 每 Worker 各自缓存 Terrarium 并行度增加会重复占用内存 load_height_tile() Worker heap 和缓存命中率
瓦片专用 Asio 池为单线程 高并发磁盘瓦片吞吐可能串行 Ucoro_Drogon_Glue 并发请求吞吐、网络线程采样
上传替换基站 GLB 时横向节点名依赖 Node 新模型节点命名不一致会失去横向显示比例 base_station_node_transformations() 上传不同节点名 GLB 验证
气压高度、Terrarium 正高和 Cesium 椭球高基准可能不同 LOS 和设备高度产生系统偏差 base_station_heights() 使用已知测量点对照
前端没有独立单元测试脚本 增量、缓存和生命周期回归主要依赖集成测试 package.json 增加 Vitest/Playwright 关键路径测试

16. 源码索引

子系统 入口类型或函数 文件位置 说明
进程 psc_main() module/Local_Server_main.cpp 后端启动和退出
全局对象 Global Global.h 配置和模块所有者
Web 服务 init_web_server() server.cpp HTTP/WS 注册
配置 Config Config.h 单一 JSON 配置
协程 Coro io_coro.cpp 网络和处理线程
数据源 Data_Source Data_Source.h 输入抽象
协议处理 Data_Source_Handler Data_Source_Handler.cpp 切包和业务分发
SSR parse_mode_s_bin() Aircraft_Info.cpp Mode S 主入口
CPR surface_position() CPR.cpp 位置和距离
实时流 register_aircraft_stream_ws() Database.cpp 版本增量 WebSocket
瓦片 init_tiles() tiles.cpp 影像/地形 HTTP
SPA App App.tsx 路由和延迟加载
统一模型 Aircraft_Model Aircraft_Model.tsx 2D/3D 共用
二维地图 Leaflet_Map Leaflet_Map.tsx Leaflet 渲染
三维地图 Cesium_Map Cesium_Map.tsx Cesium 适配器
地形 Terrarium_Terrain_Provider Terrarium_Terrain_Provider.tsx Heightmap Provider
LOS calculate_los() Los_Worker.ts Worker 通视计算
相机 Cesium_Camera_Control Cesium_Camera_Control.ts 三种控制模式

17. 无法确认的问题

  1. 没有运行目标规模压力测试,无法确认 1,000 架飞机、10,000 个轨迹点时的主线程、GPU 和 Worker 队列上限。
  2. 当前源码没有给出所有实际部署设备的高度基准,无法确认气压高度、正高和椭球高是否已经统一。
  3. 未获得生产数据库规模和索引统计,无法确认历史轨迹查询成本。
  4. 未看到浏览器端自动化测试,无法从源码确认重复进入/退出 3D、WebGL 初始化失败和 Worker 销毁的长期稳定性。
  5. GLB 上传接口允许替换模型,但无法从配置确认每个外部模型的根节点命名、坐标轴、原点和单位。
  6. Cesium、WebView2 和 Intel 集成显卡的实际驱动组合只能通过目标机器运行验证,源码不能证明 WebGL 初始化一定成功。
  7. LOS 是地形几何通视,不包含建筑、植被、天线方向图、信号强度、菲涅耳区和大气折射;这些能力当前源码未实现。