当前位置: 首页 > news >正文

全栈之路2---架构设计

前情提要

上一篇我们解决了"能不能通"的问题:用 C++ Socket 自建通信层,替代了 SFTP 定时轮询,实现了秒级上报。但通信层一旦跑通,紧接着就要回答两个问题:怎么保证安全?怎么做到可扩展?

这篇我们把架构定下来。

一、安全:Server 是唯一的挡板

既然数据库不直接暴露,那 Server 的监听端口就成了唯一的攻击面。我们不能只依赖防火墙,必须在协议层做几道关卡。

1.1 两道连接门槛

模式

说明

适用场景

开放模式

符合协议格式即可连,只校验魔数和帧长

内网可信环境,快速部署

授权模式

需携带有效 Token 才能完成注册

生产环境,默认开启

Client 首次连接时,先走 REGISTER 帧。若 Server 配置为授权模式,帧载荷必须包含 Token,否则直接断连。

1.2 Token 的传输:用 RSA 做端到端加密

  1. Token 不能明文传。我们在部署阶段预置密钥对:
  2. Server:持有私钥,用于解密 Client 上报的 Token
  3. Client:持有公钥,用于加密本地 Token

Client: Token(明文) --[RSA公钥加密]--> Token(密文) --传输--> Server --[RSA私钥解密]--> 校验

这样即使抓包,拿到的也只是密文。Token 本身定期由 Admin 统一轮换。

1.3 连接保持:SessionID + Seq

Token 只验一次,后续靠会话机制防重放和劫持:

  1. SessionID:注册成功后 Server 下发,32 字节随机串,后续每帧必带
  2. Seq:每帧自增,Server 校验连续性,跳号或复用直接断连

1.4 文件传输的安全边界

Client 支持文件上报(如日志、dump),但必须设死几条红线:

cpp

// 文件名安全检查示例

bool ValidateFilename(const std::string& name) {

if (name.empty() || name.size() > 128) return false;

if (name[0] == '/' || name[0] == '\\') return false; // 拒绝绝对路径

if (name.find("..") != std::string::npos) return false; // 拒绝路径穿越

if (name.find('\0') != std::string::npos) return false; // 拒绝截断

return true;}

// 文件大小检查if (file_size > MAX_FILE_SIZE) { // 例如 50MB

return ERR_FILE_TOO_LARGE;}

原则:通信层只认"文件名"和"二进制流",不认路径。Server 端按 session_id + timestamp + filename 落盘,杜绝 Client 指定存储位置。

二、扩展性:通信层不动,应用层随便改

安全有了,但如果每次加一张表、加一个功能都要改 C++ 通信代码,这架构就是死的。我们要做到通信层一次写死,业务层随意扩展

2.1 Client 端:指令转 Shell

Client 本地维护一个指令表。Server 下发指令时,Client 不做业务处理,而是调用 Shell完成:

cpp

// Client 指令处理极简逻辑

if (frame.type == CMD_EXEC) {

std::string cmd = ParseCmdFromPayload(frame.payload);

// 白名单校验(可选)

if (Whitelist::Contains(cmd)) {

system(cmd.c_str()); // 或 popen 捕获输出

}}

新增采集项?不用改 Client。Server 下发一条新指令即可。

2.2 Client 端:文件传输独立封装

文件传输走独立帧类型,与指令、数据上报解耦:

plain

FRAME_TYPE_FILE_START // 通知文件名、大小、MD5

FRAME_TYPE_FILE_CHUNK // 传输分片

FRAME_TYPE_FILE_END // 校验完成

应用层想传文件,就调用封装好的接口,与定时任务上报互不干扰。

2.3 Server 端:通信与入库解耦

Server(C++)只负责三件事:收数据、鉴权、转发。它绝不直接连数据库。

Server 收到数据后,通过本地 IPC(Unix Domain Socket 或 TCP 回环)丢给DB Service(Python 服务):

[Server: C++] -->(protobuf/json)--> [DB Service: Python] --> [MySQL/TDengine]

好处显而易见:

  1. C++ 专注高并发网络,Python 专注数据建模和入库
  2. 加新表?改 Python 的 ORM,C++ 不用动
  3. DB Service 崩溃?Server 把数据暂存本地队列,DB Service 重启后继续消费

2.4 管理端:独立的 Admin Client

不把管理功能做进 Web Server 进程,而是单独做一个Admin Client

  1. Web 后台下发管理指令(如:更新 Token、下发脚本、查询 Agent 状态)
  2. Admin Client 作为特殊 Client,连到 Server,拥有更高权限的指令集
  3. Server 对 Admin Client 的帧做额外标记校验(如 FLAG_ADMIN = 0x80)

这样 Web 层完全无状态,重启不影响已建立的 Agent 连接。


三、两条链路

以上设计落地后,系统形成两条清晰的链路:

上行链路(数据上报)

Shell/采集脚本

--> zmAgent(Client)

--> zmServer(C++)

-->db_service(Python)

--> Database

--> WebServer

--> 前端展示

下行链路(指令下发)

Web 管理台

--> WebServer

--> zmAdmin(Admin Client)

--> zmServer(C++)

--> zmAgent(Client)

--> Shell 执行

--> 结果返回(可选走上行链路回传)

Server 是枢纽,但只做转发,不碰业务逻辑。

整体架构示意图如下:


四、协议头定义(示例版)

结合安全和扩展需求,协议头定死为 12 字节固定头 + 变长载荷:

cpp

#pragma pack(push, 1)

struct ProtocolHeader {

uint8_t magic; // 0x5A 'Z'

uint8_t version; // 0x01

uint8_t type; // 帧类型

uint8_t flags; // 标志位

uint16_t length; // 载荷长度,大端

uint32_t seq; // 序列号,大端

uint32_t session; // 会话标识(注册前为0)

};

#pragma pack(pop)

flags 位定义:

表格

含义

0x01

是否加密(RSA/AES)

0x02

是否压缩(zlib)

0x04

是否分片(大文件/大数据)

0x80

是否管理帧(Admin Client 专属)

帧类型(部分):

cpp

enum FrameType : uint8_t {

HEARTBEAT = 0x01,

REGISTER = 0x02,

REGISTER_ACK= 0x03,

REPORT = 0x10, // 指标上报

CMD_EXEC = 0x20, // 指令下发

CMD_RESULT = 0x21, // 指令结果

FILE_START = 0x30,

FILE_CHUNK = 0x31,

FILE_END = 0x32,

ADMIN_CMD = 0x40 // 管理指令

};

魔数 + 版本 + 类型 + 标志 + 长度 + Seq + Session,12 字节。Server 收包时先读 12 字节,校验魔数和长度,再读载荷。粘包、错包一眼识别。


五、小结

这一篇我们把骨架搭好了:

  1. 安全:Token + RSA 防窃听,Session + Seq 防重放,文件名白名单防穿越
  2. 扩展:Client 转 Shell、文件传输独立接口封装、Server 与入库解耦、Admin 独立
  3. 链路:上行采集,下行管控,Server 只做枢纽
  4. 协议:12 字节定长头,支持加密、压缩、分片、管理标记

下一篇:《全栈之路3---zmagent 开发实现》,我们开始写代码,先把 Client 端跑起来。

http://www.jsqmd.com/news/1405322/

相关文章:

  • 学术党必收藏✅为什么专业写论文都只用OKBIYE?
  • 具有转储功能的电池供电的低功耗电导率传感器-几个关键参数的确定
  • DepotDownloader 完整实战指南:3 分钟跑通首个 Steam Depot 下载任务
  • SDC命令详解:使用current_design命令设置当前设计
  • 2026年8月汉中外墙漏水维修靠谱渠道盘点,高层高空渗水修缮避坑指南 - 聪居到家
  • AnimateLCM生态资源汇总:HuggingFace Demo、Civitai模型与社区玩法
  • 唐山路北区宅仕达漏水检测维修全城上门2026全网口碑优选:防水补漏公司#唐山 - 超人防水
  • 2026超全测评|5款主流教案教学设计工具对比,教师备课神器首选
  • 2026抢抓AI数字营销新机遇 艾奇在线中高端AI官网建设核心服务体系全解析 - U渠道
  • 8GB显存也能跑视频生成大模型?ComfyUI-WanVideoWrapper 的显存优化路线图
  • 湖南阳光无人机维修培训基地精讲无人机整机五大核心系统 - 湖南阳光技术
  • 艾尔登法环帧率解锁终极攻略:EldenRingFpsUnlockAndMore 免费工具完整教程
  • SDN架构原理自动化运维全攻略
  • 华硕笔记本轻量控制工具 G-Helper 完整指南:不到10MB,三步告别 Armoury Crate 卡顿
  • 人体姿势检索实战指南:用 Pose-Search 三步从海量图片中找出指定动作
  • 2026年无锡丰田车主必看!音尚阁5大方案解汽车音响升级之困,汽车音响升级**门店选哪家 - 企业权威推荐大使
  • 青岛李沧区宅仕达漏水检测维修全城上门 2026 全网口碑优选:防水补漏公司 #青岛 - 超人防水
  • 洛雪音乐音源导入全攻略:免费解锁多平台无损音乐的极简方案
  • 内行不公开✅OKBIYE七大顶配功能|吊打市面普通AI论文工具
  • 流放之路Build规划终极指南:5分钟用Path of Building离线算出真实伤害
  • 你的微信聊天记录真的属于你吗?用WeChatMsg把十年对话永久留在本地
  • 2026年去内蒙古,你需要的不是攻略,而是一个对的人——七位持证导游真实揭秘 - 纯玩旅游分享
  • 电动车专线物流哪个便宜靠谱?2026年托运避坑全攻略 - 快递物流资讯
  • Ventoy 启动盘完全指南:一次安装,让一个 U盘装下所有系统
  • Windows 10 运行 Android 应用终极指南:把 Windows 11 的安卓子系统搬进老电脑
  • 5分钟上手PingFangSC字体:网页与文档快速用上苹果级中文显示效果
  • 福州台江宅仕达漏水检测维修全城上门 2026 全网口碑优选:防水补漏公司 #福州 - 超人防水
  • 3步上手LosslessCut:免费无损视频剪辑,大文件也能几秒导出
  • 2026新疆沙漠玫瑰选购指南:探访喀什欧亚国际大巴扎 - 互联网科技品牌测评
  • 接口自动化测试平台(ITP)操作说明