Files
Inbox/系统基座文件/2/2.4/2.4.1 传输层拓扑与套接字模型 (Transport Layer Topology & Socket Model).md
2025-12-11 07:24:36 +08:00

99 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
tags: []
date created: 星期一, 十一月 24日 2025, 4:14:06 下午
date modified: 星期一, 十一月 24日 2025, 4:48:23 下午
---
# 2.4.1 传输层拓扑与套接字模型 (Transport Layer Topology & Socket Model)
## 1. 传输拓扑UDP 单播直连 (UDP Unicast Direct)
- **基线决策**:采用 **UDP 单播 (Unicast)**,由 `DisplayController` 绑定本地网卡,直接向配置的显控终端 IP 发送数据。
- **设计论证**
- **去中心化**避免了组播Multicast对交换机 IGMP Snooping 配置的依赖,降低部署复杂度。
- **无状态**:相比 TCPUDP 无需维护连接状态(三次握手/四次挥手),消除 `TIME_WAIT` 资源占用最适合“发后即忘Fire-and-Forget”的遥测场景。
- **隔离性**点对点发送天然隔离了网络风暴若存在多个显控终端建议通过应用层复制分发Application-Layer Fanout而非网络层组播以实现对不同终端的差异化流控例如给指挥屏发全量数据给监控屏发降级数据
## 2. 套接字模型:非阻塞 + 边缘触发 (Non-blocking + Epoll ET)
为了支撑高频率(如 100Hz+)的数据刷新而不阻塞业务线程,必须采用全异步 I/O 模型。
- **模式基线****Non-blocking Socket** + **Epoll Edge Triggered (ET)**
- **核心策略:“写优先,等其次” (Write-First, Wait-Later)**
- **传统误区**:很多设计是先 `epoll_wait` 等到 `EPOLLOUT` 再写。这在高吞吐场景下是低效的,因为 99% 的时间网络都是可写的,无谓的 `epoll_wait` 增加了系统调用开销。
- **基线逻辑**
1. **直接发送**:业务线程或发送线程直接调用 `sendto()`
2. **处理拥塞**:仅当 `sendto()` 返回 `EAGAIN` / `EWOULDBLOCK`(内核缓冲区满)时,才将 Socket 加入 `epoll` 监听 `EPOLLOUT` 事件。
3. **恢复发送**:当 `epoll` 通知可写时,继续发送剩余数据,并立即移除监听,回归“直接发送”模式。
## 3. 关键配置参数深度解析 (Parameter Tuning)
这里我们不硬定“8MB”而是给出**基于场景的计算逻辑**。
### 3.1 发送缓冲区 (`SO_SNDBUF`):突发吸收器
- **设计目标**:吸收 **微突发 (Micro-burst)**。雷达数据通常是脉冲式的,一个 CPI 处理完会瞬间产生大量点迹/航迹数据。Socket 缓冲区必须足够大,能完全容纳“最大可能的单次突发数据量”,让网卡以物理线速慢慢发出去,而不是让应用程序阻塞。
- 计算公式:
$$
\text{Target Buffer} = \text{Max\_Burst\_Size} \times \text{Safety\_Factor}$$
- _Max_Burst_Size_假设最大工况下一帧CPI产生的点迹 + 航迹 + 回波切片总大小。例如1000 个点迹 (x 64B) + 200 航迹 (x 128B) + 回波切片 (256KB) $\approx$ 350KB。
- _Safety_Factor_考虑到 OS 调度抖动,可能连续积压 2-3 帧数据。取系数 4。
- _计算结果_$350\text{KB} \times 4 \approx 1.4\text{MB}$。
- **配置建议**
- **基线值**:动态计算或设置为 **4MB - 8MB**(留有充足余量)。对于现代服务器内存而言,这个开销极低,但收益(零阻塞)巨大。
- **实施**`setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, …)`。注意 Linux 内核会将设置值翻倍以用于元数据,实际可用空间即为设定值。
### 3.2 服务质量标记 (`IP_TOS` / DSCP):网络特权
- **设计目标**告诉交换机和路由器这股数据流是“VIP”在网络拥塞时优先转发最后丢弃。
- **参数选择**
- **DSCP (Differentiated Services Code Point)**:推荐使用 **EF (Expedited Forwarding, 0x2E)****CS6 (0x30)**。这是仅次于网络控制信令CS7的最高优先级通常用于 VoIP 语音或实时控制数据。
- **实施**
```cpp
int tos = 0xB8; // DSCP EF (101110) << 2
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
```
### 3.3 路径 MTU 发现 (PMTU Discovery):避免分片
- **现状**:虽然采集链路用了 JUMBO Frame (9000),但**显控链路通常经过普通交换机或公网MTU 往往限制在 1500**。
- **策略**
- **强制禁止分片 (`IP_MTU_DISCOVER` = `IP_PMTUDISC_DO`)**:让内核在数据包超过 MTU 时直接报错 `EMSGSIZE`而不是默默分片IP 分片会严重降低 UDP 可靠性,一个分片丢失导致整个包作废)。
- **应用层分包**`DisplayController` 必须根据实际 MTU如 1472 字节 Payload在应用层进行切片Fragmentation。这与我们后续 2.4.2 的“Atomic Batch”设计不冲突一个 Batch 可以被切成多个 UDP 包发送,只要包含相同的 `BatchID` 和 `SequenceID` 即可。
## 4. 高效线程模型 (The "Pumper" Thread)
为了彻底隔离网络抖动对计算核心的影响,我们确立 **独立发送线程** 模型。
- **架构**
- **生产者**`SignalProcessor` 计算完毕,将 `DetectionResult` 对象放入一个 **SPSC (单生产单消费) 无锁队列**。
- **消费者 (DisplayController IO Thread)**
- 绑定到非关键 CPU 核心(如 Core 14
- 死循环从队列取数据。
- 执行 Protobuf 序列化。
- 执行 `sendto()`。
- 若 `EAGAIN`,则 `epoll_wait()`。
- **收益**
- **序列化卸载**Protobuf 序列化是 CPU 密集型操作,将其移出信号处理主线程,保护了核心计算资源。
- **故障隔离**即使网络断开、Socket 缓冲区塞满,影响的也只是这个 IO 线程(队列满后丢弃新数据),绝不会阻塞 FFT/CFAR 运算。
---
## 总结2.4.1 基线图谱
|**配置项**|**核心基线**|**设计意图**|
|---|---|---|
|**拓扑**|**UDP Unicast**|简单、高效、无状态。|
|**I/O 模型**|**Non-blocking + Epoll ET**|" 写优先 " 策略,最大化吞吐,最小化系统调用。|
|**发送缓冲**|**动态计算 (Max Burst x 4)**|约 4MB-8MB。吸收脉冲式突发防止应用层阻塞。|
|**QoS**|**DSCP EF / CS6**|确保在交换机侧的转发优先级。|
|**分片策略**|**禁止 IP 分片 + 应用层切分**|避免 IP 分片重组风险,提升丢包恢复能力。|
|**线程模型**|**独立 IO 线程 + SPSC 队列**|隔离网络抖动与序列化开销,保护计算核心。|
**提问**:您是否确认 **“非阻塞 +Epoll ET”** 模型以及 **“独立线程序列化与发送”** 的架构基线?确认后我们将进入 **2.4.2 业务数据序列化规范**,讨论数据具体怎么“打包”。