输入关键词开始搜索

系统架构设计

02 — 云融(YunRong)· 系统架构设计文档

前置文档01-需求分析文档

版本:v0.1 状态:已发布 最后更新:2025-01


1. 架构概述

1.1 设计目标

目标说明
分层解耦上层不依赖下层实现细节,面向接口编程,层间通过明确的数据结构传递
网络优先网络层作为一等公民独立成层,具备完整的连接管理、协议编解码、可靠性保障能力
GUI 不阻塞任何可能阻塞的操作(网络 IO、文件读写、数据库查询)均在非 GUI 线程执行
可测试性核心业务逻辑不依赖 Qt GUI 类,可脱离界面运行单元测试
跨平台平台差异代码隔离在 Platform Abstraction Layer,核心代码 100% 跨平台

1.2 四层架构

┌────────────────────────────────────────────────────────────┐
│                   Presentation Layer (GUI)                  │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │
│  │ 主窗口    │ │ 聊天视图  │ │ 联系人树  │ │ 数据统计面板  │  │
│  │ MainWin  │ │ ChatView │ │ OrgTree  │ │ Dashboard   │  │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘  │
│       └─────────────┴────────────┴───────────────┘          │
│                          │ Qt Signal/Slot                   │
├──────────────────────────┼──────────────────────────────────┤
│                   Application Layer (业务逻辑)               │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │
│  │ IMService│ │TaskService│ │FileService│ │ReportService │  │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘  │
│       └─────────────┴────────────┴───────────────┘          │
│                          │ C++ 接口                         │
├──────────────────────────┼──────────────────────────────────┤
│                     Service Layer (服务层)                    │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │
│  │NetworkMgr│ │ DataMgr  │ │ConfigMgr │ │  LogService  │  │
│  │ WS+HTTP  │ │SQLite +  │ │          │ │              │  │
│  │          │ │Remote HTTP│ │          │ │              │  │
│  └────┬─────┘ └────┬─────┘ └──────────┘ └──────────────┘  │
│       │            │                                        │
├───────┼────────────┼────────────────────────────────────────┤
│       │    Infrastructure Layer (基础设施)                   │
│  ┌────┴────────────┴──────┐ ┌──────────┐ ┌──────────────┐  │
│  │   ThreadPool / Queue   │ │ Crypto   │ │ Serialization │  │
│  │   (多线程 + 无锁队列)   │ │ (TLS)    │ │ (JSON/Binary) │  │
│  └────────────────────────┘ └──────────┘ └──────────────┘  │
└─────────────────────────────────────────────────────────────┘

2. 模块分解

2.1 模块总览

client/src/
├── core/                        # 核心库(无 Qt GUI 依赖)
│   ├── net/                     # 网络通信层 ⭐核心强化模块
│   │   ├── connection_mgr.cpp   # 连接管理器(连接池 + 生命周期)
│   │   ├── ws_client.cpp        # WebSocket 客户端
│   │   ├── http_client.cpp      # HTTP 客户端
│   │   ├── heartbeat.cpp        # 心跳保活
│   │   ├── reconnect_strategy.cpp # 断线重连策略
│   │   ├── protocol.cpp         # 协议编解码(JSON 帧 + 二进制帧)
│   │   └── rate_limiter.cpp     # 流控 / 限速
│   ├── data/                    # 数据访问层
│   │   ├── i_data_store.h       # 存储抽象接口 (Strategy 模式)
│   │   ├── sqlite_store.cpp     # SQLite 实现
│   │   ├── sync_mgr.cpp         # 同步管理器
│   │   └── cache_mgr.cpp        # 本地缓存管理
│   ├── model/                   # 数据模型(纯数据结构,跨层共享)
│   │   ├── message.cpp          # 消息
│   │   ├── conversation.cpp     # 会话
│   │   ├── contact.cpp          # 联系人
│   │   ├── task.cpp             # 任务
│   │   └── file_transfer.cpp    # 传输任务
│   ├── service/                 # 业务服务
│   │   ├── im_service.cpp       # IM 业务逻辑
│   │   ├── task_service.cpp     # 任务业务逻辑
│   │   ├── file_service.cpp     # 文件传输业务逻辑
│   │   └── report_service.cpp   # 报表业务逻辑
│   └── infra/                   # 基础设施
│       ├── thread_pool.cpp      # 线程池
│       ├── msg_bus.cpp          # 线程间消息总线(无锁队列)
│       ├── config_mgr.cpp       # 配置管理 (Singleton)
│       ├── logger.cpp           # 日志服务
│       └── crypto.cpp           # 加密工具

├── gui/                         # GUI 层(依赖 Qt Widgets)
│   ├── main_window.cpp          # 主窗口(导航 + 内容区 + 信息面板)
│   ├── views/
│   │   ├── chat_view.cpp        # 聊天视图(消息气泡列表 + 输入框)
│   │   ├── contact_tree.cpp     # 组织架构树
│   │   ├── task_list.cpp        # 任务列表
│   │   ├── file_panel.cpp       # 文件传输面板
│   │   └── dashboard.cpp        # 数据统计面板
│   ├── widgets/                 # 自定义控件
│   │   ├── message_bubble.cpp   # 消息气泡 Delegate
│   │   ├── avatar_widget.cpp    # 头像控件
│   │   ├── speed_chart.cpp      # 实时传输速度曲线
│   │   ├── toast_notify.cpp     # Toast 通知弹窗
│   │   └── status_indicator.cpp # 在线状态指示灯
│   ├── models/                  # Qt Model 适配层
│   │   ├── conversation_model.cpp
│   │   ├── message_list_model.cpp
│   │   └── contact_tree_model.cpp
│   └── delegates/               # 自定义渲染
│       └── message_delegate.cpp

├── app/
│   └── main.cpp                 # 应用入口

├── tests/                       # 测试
│   ├── unit/                    # 单元测试
│   └── integration/             # 集成测试

2.2 模块职责矩阵

模块职责依赖
net/connection_mgr管理所有 TCP/WS/HTTP 连接的生命周期,提供连接池infra/thread_pool
net/ws_clientWebSocket 连接、帧收发、Ping/Pongnet/protocol, Qt WebSocket
net/http_clientHTTP 请求/响应、多线程下载Qt Network, net/protocol
net/protocolJSON 帧编解码、二进制帧编解码、序列号管理nlohmann/json
net/heartbeat定时 Ping,超时检测,触发重连net/ws_client
net/reconnect_strategy指数退避重连算法、状态机net/connection_mgr
data/sqlite_store本地数据 CRUD、全文搜索SQLite3 C API
远程数据通过 Go 后端 REST API 访问,客户端不直连 PostgreSQL
data/sync_mgr增量同步引擎,冲突检测data/*_store
service/im_service消息路由、会话管理、未读计数net/*, data/*
service/file_service上传/下载编排、断点续传逻辑net/http_client
gui/chat_view消息气泡渲染、输入处理、滚动优化service/im_service
gui/widgets/*通用可复用控件Qt Widgets

3. 设计模式应用总览

设计模式是架构的”关节”——决定模块间如何协作。以下标注了每个模式的具体落点。

#设计模式落点模块动机
1Observer全层:Service → GUI 通过 Signal/Slot解耦数据生产与消费,实时推送
2Strategydata/i_data_store — SQLite vs PG;报表导出 CSV/PDF/JSON运行时/编译时切换实现
3Singletoninfra/config_mgr, infra/logger全局唯一实例,Meyer’s Singleton(connection_mgr 非 Singleton——将来可能多服务端连接)
4Commandnet/ — 网络请求对象化(SendMsgCmd, UploadCmd)支持队列/重试/撤销网络请求参数化 + 重试队列
5Factory Methodnet/connection_mgr — 根据协议类型创建 WS/HTTP 连接URL scheme → 对应 Client
6Statenet/reconnect — IDLE → CONNECTING → CONNECTED → RECONNECTING → ERROR避免 if-else 地狱,状态转移显式化
7Producer-Consumerinfra/msg_bus — Main Thread ↔ Worker Pool ↔ DB Thread 之间通过线程安全队列传递消息无锁队列削峰,保证 GUI 不卡
8Decoratorservice/ — 消息处理管线:解密→校验→去重→存储→通知可组合的数据处理链
9Facadenet/connection_mgr — 对外隐藏 WS/HTTP/文件传输的复杂性统一入口,降低上层使用复杂度
10Adaptergui/ + infra/ — 系统托盘、通知、凭据存储中通过 #ifdef PLATFORM_* 条件编译隔离平台差异隔离 OS 差异

4. 线程模型设计

4.1 线程拓扑

┌─────────────────────────────────────────────────────────┐
│                     Thread Architecture                   │
│                                                          │
│  ┌──────────────────────────────────────────────────┐   │
│  │   Main Thread (Qt Event Loop)                     │   │
│  │   • GUI 渲染/事件 + Signal/Slot 调度              │   │
│  │   • QWebSocket / QNetworkAccessManager (异步 IO)  │   │
│  │   • QTimer 心跳 / Token 刷新 / 统计聚合           │   │
│  │   • 轻量级消息路由(接收后直接分发,不做重计算)    │   │
│  └────────┬─────────────────────────────────────────┘   │
│           │ QueuedConnection (跨线程 Signal)              │
│  ┌────────┴────────────────────────────────────┐        │
│  │          Message Bus (线程安全队列)            │        │
│  └────────┬────────────────────────────────────┘        │
│           │                                              │
│  ┌────────┴──────┐ ┌──────────────┐ ┌──────────────┐    │
│  │ Worker Pool    │ │  DB Thread    │ │  File Pool    │    │
│  │ (N workers)    │ │ (SQLite 串行) │ │ (N workers)   │    │
│  │                │ │               │ │               │    │
│  │ • Protocol     │ │ • 消息 CRUD   │ │ • 分块上传    │    │
│  │   编解码       │ │ • 离线缓存    │ │ • 分块下载    │    │
│  │ • 加密/解密    │ │ • 搜索查询    │ │ • Hash 校验   │    │
│  │ • 消息校验     │ │               │ │               │    │
│  └───────────────┘ └──────────────┘ └───────────────┘    │
└─────────────────────────────────────────────────────────┘

4.2 线程间通信机制

Main Thread              Worker Pool             DB Thread           File Pool
(GUI + Async IO)             |                       |                   |
     │                        |                       |                   |
     │── RawMessage ─►[Signal]│                       |                   |
     │                        │ 1. 解码/校验/解密      |                   |
     │◄── DecodedMsg ─[Signal]│                       |                   |
     │                        │                       |                   |
     │── StoreMsg ──[Signal]──┼──────────────────────►│                   |
     │                        │                       |                   |
     │◄── QueryResult ───────┼──────────[Signal]─────│                   |
     │                        │                       |                   |
     │── UploadTask ─[Signal]─┼──────────────────────┼──────────────────►│
     │                        │                       |                   |
     │◄── Progress ──────────┼──────────────────────┼──────[Signal]─────│
通道机制方向数据
Main → WorkerPoolQt Signal (QueuedConnection)单向原始网络字节(RawMessage)
WorkerPool → MainQt Signal (QueuedConnection)单向解码/校验后的消息(DecodedMsg)
Main → DBQt Signal (QueuedConnection)单向待持久化的消息、查询请求
DB → MainQt Signal (QueuedConnection)单向查询结果、同步完成通知
Main → FilePoolQt Signal (QueuedConnection)单向上传/下载任务
FilePool → MainQt Signal (QueuedConnection)单向进度更新、完成通知

4.3 关键线程安全规则

规则说明
SQLite 单线程写入SQLite 的 WAL 模式支持多读单写,但为了简化,所有 SQLite 写操作串行化到一个 DB Thread
异步 IO 在主线程 + 批量/重计算在 Worker PoolQWebSocket / QNetworkAccessManager 的异步 IO 回调在主线程触发。单条消息的编解码在主线程直通(JSON 解析 2-5μs,避免跨线程调度开销更大)。Worker Pool 仅用于:① 离线同步时的批量消息解码 ② AES 加解密 ③ 文件 SHA-256。解码完成后回传主线程进行 GUI 更新和持久化分发
文件传输用线程池大文件分块上传/下载可并行,每块在池中独立执行,完成后汇总
共享状态用 shared_mutex配置对象、联系人缓存等读多写少的数据,用 std::shared_mutex 保护
GUI 线程零等待GUI 线程绝不调用 wait()join()mutex.lock()(可能阻塞的)——只发信号和读无锁队列

5. 网络层架构(核心强化)

5.1 网络分层

┌─────────────────────────────────────────┐
│        application layer 调用            │
│   sendMessage() / uploadFile() / ...    │
├─────────────────────────────────────────┤
│          ConnectionManager               │
│   • 连接池管理                            │
│   • 请求路由 (WS vs HTTP vs File)        │
│   • 命令队列 + 重试                       │
├──────────────┬──────────────────────────┤
│   WsClient   │     HttpClient            │
│   • 长连接    │     • 短连接池             │
│   • 帧收发    │     • REST 请求            │
│   • Ping/Pong│     • 分块传输             │
├──────────────┴──────────────────────────┤
│          Protocol Layer                  │
│   • JSON 帧编解码                         │
│   • 二进制帧编解码                         │
│   • 序列号 / ACK 管理                     │
├─────────────────────────────────────────┤
│          Transport Layer                 │
│   • Qt Network (TCP / QWebSocket)        │
│   • QSslSocket (TLS)                     │
│   • Socket 选项 (TCP_NODELAY, KEEPALIVE) │
└─────────────────────────────────────────┘

5.2 连接状态机

                    ┌──────────┐
        startup ──► │  IDLE    │
                    └────┬─────┘
                         │ connect()
                    ┌────▼─────┐
              ┌────►│CONNECTING├────┐
              │     └────┬─────┘    │ TLS handshake timeout
              │          │ success  │ (10s)
              │     ┌────▼─────┐    │
              │     │CONNECTED │◄───┘
              │     └────┬─────┘
              │          │ heartbeat fail (3次)
              │          │ 或 网络断开
              │     ┌────▼──────┐
              │     │RECONNECT  │
              │     │ING        │
              │     └────┬──────┘
              │          │ 指数退避: 1s→2s→4s→8s→16s→30s→60s
              └──────────┘
                        │ 超过最大重试次数 (10次)
                   ┌────▼─────┐
                   │   ERROR   │──► 通知用户手动重连
                   └──────────┘

5.3 协议帧设计

JSON 控制帧(WebSocket Text 帧)

{
  "ver": 1,
  "type": "msg|ack|notify|heartbeat|sync|error",
  "seq": 12345,
  "ts": 1704067200000,
  "payload": {}
}
字段类型说明
verint协议版本号,当前为 1
typestring帧类型,决定 payload 结构
sequint32单调递增序列号,用于 ACK 对应和去重
tsint64Unix 毫秒时间戳
payloadobject根据 type 变化的具体数据

二进制帧(文件传输 / 缩略图)

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Total Length (32-bit)                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Type (8bit)  |             Payload Data ...                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段大小说明
Total Length4 Bytes帧总长度(不含自身),大端序
Type1 Byte0x01 缩略图, 0x02 文件块, 0x03 ACK
Payload变长数据载荷

5.4 ACK 与重传机制

Client (发送方)                     Server (接收方)
     │                                   │
     │── msg(seq=100, type="msg") ─────►│
     │                                   │── 存储消息
     │◄── ack(seq=100) ────────────────│
     │                                   │
     │   [标记已送达]                      │
     │                                   │
     │── msg(seq=101) ───────── X 丢失   │
     │                                   │
     │   [5s 超时, 重发 seq=101]          │
     │── msg(seq=101, retry=1) ────────►│
     │◄── ack(seq=101) ────────────────│
  • 发送方维护 map<seq, SentRecord>,包含发送时间、重试次数、回调
  • 定时器每 1s 扫描一次,重发超时未 ACK 的消息(最多 3 次)
  • 接收方维护 last_recv_seq,收到的 seq <= last_recv_seq 视为重复,直接回复 ACK 但丢弃

6. 数据流设计

6.1 消息发送全流程

Main Thread          Worker Pool           Server            DB Thread
     │                    │                    │                  │
     │ sendMessage(msg)   │                    │                  │
     │───────────────────►│                    │                  │
     │                    │ 1. Protocol 编码    │                  │
     │                    │    分配 seq        │                  │
     │                    │    序列化 JSON      │                  │
     │◄── EncodedFrame ───│                    │                  │
     │                    │                    │                  │
     │ 2. 写入发送缓冲      │                    │                  │
     │                    │                    │                  │
     │──────────────────────── WS Send ───────►│                  │
     │                    │                    │                  │
     │◄─────────────────────── WS ACK ────────│                  │
     │                    │                    │                  │
     │ 3. 标记已送达        │                    │                  │
     │ 4. 更新气泡: 已送达   │                    │                  │
     │                    │                    │                  │
     │── StoreMsg ────────────────────────────────────►[Signal]──│
     │                    │                    │      持久化       │

6.2 消息接收全流程

Server      Main Thread          Worker Pool           DB Thread
 │               │                    │                    │
 │── WS msg ───►│                    │                    │
 │               │ 收到原始字节         │                    │
 │               │                    │                    │
 │               │── RawBytes ───────►│                    │
 │               │                    │ 1. Protocol 解码   │
 │               │                    │ 2. 校验 seq        │
 │               │                    │ 3. 去重检查        │
 │               │                    │ 4. 解密 (如需要)   │
 │               │◄── DecodedMsg ─────│                    │
 │               │                    │                    │
 │               │ 5. 发送 ACK         │                    │
 │───────────────│── WS ACK ─────────►│                    │
 │               │                    │                    │
 │               │── StoreMsg ────────────────────►[Signal]│
 │               │                    │       6. 写入 SQLite│
 │               │                    │       7. 更新会话摘要│
 │               │                    │                    │
 │               │◄── NewMsg ────────────────[Signal]─────│
 │               │                    │                    │
 │               │ 8. 更新聊天列表      │                    │
 │               │ 9. 当前会话: 追加气泡 │                    │
 │               │10. 后台: 托盘+Toast  │                    │

6.3 文件上传流程

Main Thread          File Pool              Server
   │                    │                    │
   │ uploadFile(path)   │                    │
   │───────────────────►│                    │
   │                    │ 1. SHA-256 文件    │
   │                    │                    │
   │                    │── CheckHash ──────►│
   │                    │◄── 已存在? ───────│ (秒传判断)
   │                    │                    │
   │                    │ [不存在, 分块上传]  │
   │                    │                    │
   │                    │── Chunk 0 ────────►│
   │◄── progress(5%) ──│                    │
   │                    │── Chunk 1 ────────►│
   │◄── progress(10%)──│                    │
   │                    │       ...          │
   │                    │── Chunk N ────────►│
   │◄── progress(100%)─│                    │
   │                    │◄── Upload OK ─────│
   │◄── uploadDone(url)─│                    │

7. 数据库设计概要

详细设计见 04-数据库设计文档.md,此处仅给架构层面的关系。

7.1 数据实体关系

┌──────────┐       ┌──────────────┐       ┌──────────┐
│  Contact  │       │ Conversation │       │ Message  │
│  (联系人)  │◄─────│  (会话)       │─────►│ (消息)    │
└──────────┘  N:M  └──────────────┘  1:N  └──────────┘

                         │ 1:N
                    ┌────┴────┐
                    │  Task   │
                    │  (任务)  │
                    └─────────┘

┌──────────────┐
│ FileTransfer │  (独立实体,记录所有传输任务)
└──────────────┘

┌──────────┐
│  Config  │  (键值对,用户偏好)
└──────────┘

7.2 存储分层策略

存储数据特征
热数据内存 (unordered_map)最近 50 个会话的摘要、在线联系人状态
温数据SQLite近 30 天消息、全部会话元数据、传输历史
冷数据PostgreSQL (服务端)全量归档消息、用户账户、组织架构
本地不存储仅服务端其他用户的敏感信息、系统配置

8. 技术选型理由

技术选择理由
C++17std::optional, std::variant, std::filesystem, if constexpr
Qt 6.9 Widgets桌面 GUI + 网络(QWebSocket + QNetworkAccessManager),零外部依赖
Go 1.22+后端服务:gorilla/websocket + Gin REST API + PostgreSQL 驱动
CMake 3.20+C++ 客户端构建
SQLite 3客户端本地存储(WAL 模式 + FTS5)
PostgreSQL 14+Go 后端远程存储(客户端不直连 PG)
nlohmann/json单头文件 JSON 库,STL-like API,用于协议编解码
spdlog高性能异步日志库,支持多 sink(文件 + 控制台 + 旋转)

9. 关键架构决策记录 (ADR)

ADR-001:客户端网络层使用 Qt 原生 API,后端用 Go

  • 背景:项目最初选择 Boost.Asio + Beast 做 WebSocket 客户端,后因依赖沉重(125MB 源码包、30s+ 增量编译、API 兼容性问题)而废弃
  • 决策:客户端网络层全部使用 Qt 原生 API(QWebSocket + QNetworkAccessManager),后端服务用 Go
  • 理由
    1. QWebSocket 与 Qt 信号槽无缝集成,网络回调直接在同一事件循环中处理
    2. 心跳用 QTimer,重连用 QTimer 延迟回调,无需 asio::steady_timer
    3. 零外部依赖——Qt 6 自带完整的网络模块
    4. Go 后端自然支持高并发 WebSocket + REST,部署简单(单二进制)
  • 代价:QWebSocket 不支持二进制帧的自定义 socket 选项,但对本项目无影响

ADR-002:SQLite 访问串行化到单独线程

  • 背景:SQLite 支持多线程(WAL 模式),可多读单写
  • 决策:所有 SQLite 访问(读写均)通过 DB Thread 的消息队列串行化
  • 理由
    1. 避免”SQLITE_BUSY”重试逻辑
    2. 写入顺序天然就是时间顺序,便于调试
    3. 客户端场景的数据库负载远未到需要并行 SQLite 的程度
  • 代价:读取也需要异步回调,增加了 API 复杂度

ADR-003:GUI 使用 Widgets 而非 QML

  • 背景:Qt 6 主推 QML,Widgets 被视为”legacy”
  • 决策:使用 Qt Widgets
  • 理由
    1. 自定义控件(消息气泡、仪表盘)用 QPainter::paintEvent 比 QML Canvas 更可控
    2. 与 C++ 核心库零距离——Model 可以直接是 C++ STL 容器的包装
    3. 需求文档要求”QTGUI+控件开发”,Widgets 是 Qt GUI 的本体
    4. QML 需要额外的 qmlRegisterType 绑定层,增加耦合

10. 构建系统设计

10.1 CMake 结构

# client/CMakeLists.txt — C++ 桌面客户端
cmake_minimum_required(VERSION 3.20)
project(YunRong VERSION 0.1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 第三方依赖 (FetchContent)
include(FetchContent)
FetchContent_Declare(nlohmann_json GIT_REPOSITORY https://github.com/nlohmann/json.git ...)
FetchContent_Declare(spdlog        GIT_REPOSITORY https://github.com/gabime/spdlog.git ...)

# 子目录
add_subdirectory(src/core)       # 核心库 (无 Qt GUI)
add_subdirectory(src/gui)        # GUI 库 (依赖 Qt Widgets)
add_subdirectory(src/app)        # 可执行文件
add_subdirectory(tests)          # 测试

# Mock Server 是独立 CMake 项目 (mock/CMakeLists.txt)

10.2 平台适配宏

# cmake/Platform.cmake
if(WIN32)
    target_compile_definitions(core PRIVATE PLATFORM_WINDOWS)
    target_link_libraries(core PRIVATE ws2_32 crypt32)
elseif(UNIX AND NOT APPLE)
    target_compile_definitions(core PRIVATE PLATFORM_LINUX)
    target_link_libraries(core PRIVATE pthread dl)
endif()

附录 A — 术语表

术语说明
ADRArchitecture Decision Record,架构决策记录
WALWrite-Ahead Logging,SQLite 的并发写模式
Proactor异步 IO 模式——OS 完成后通知,与 Reactor(就绪通知)相对
QueuedConnectionQt 跨线程信号槽连接类型,槽函数在接收者线程的事件循环中执行
Event LoopQt 主线程事件循环,QWebSocket 和 QNetworkAccessManager 均在其上异步运行

附录 B — 文档修订记录

版本日期作者变更说明
v0.12025-01初稿,完成全部章节