高性能 C++ 社交平台1:微服务架构设计

高性能 C++ 社交平台微服务架构设计

本文是 SwiftChatSystem 后端系列博客的第一篇,从整体架构视角介绍这一 C++ 微服务社交系统的设计思路与核心组件。


一、项目目标与定位

SwiftChatSystem 致力于构建一个功能完整、高性能、可演示的类 QQ 实时社交系统。不同于常见的「玩具级」聊天 Demo,本项目在以下方面有明确考量:

维度 说明
产品闭环 私聊、群聊、好友、富媒体、已读回执、离线推送等功能完整,可现场演示
技术深度 C++17 系统编程 + 微服务拆解 + 云原生部署(Kubernetes)
工程规范 gRPC IDL 定义接口、CMake 构建、配置与代码分离
可扩展性 单机 RocksDB 起步,预留 MySQL / Redis / MinIO 的演进路径

换言之,它既是一个可跑起来的「成品」,也是一份可复用的微服务架构实践样本。


二、整体架构:请求如何「走一圈」

客户端发出一条消息、发起一次好友申请,请求要经过哪些组件?我们可以用一句话概括:

客户端 → GateSvr(WebSocket)→ ZoneSvr(路由)→ 某 System → 后端 gRPC 服务 → 返回

下面用 Mermaid 流程图更直观地展示这一链路:
存储
业务服务层
Zone 内部 System
路由层
接入层
客户端(Qt / 其他)

  1. WebSocket
    cmd + payload 2. gRPC
    HandleClientRequest Desktop Client
    GateSvr

WebSocket:9090

gRPC:9091
ZoneSvr

gRPC:9092
AuthSystem
ChatSystem
FriendSystem
GroupSystem
FileSystem
AuthSvr:9094
OnlineSvr:9095
FriendSvr:9096
ChatSvr:9098
FileSvr:9100
RocksDB

请求流转的六个步骤:

  1. Client → GateSvr :通过 WebSocket 发送 { cmd, payload },例如 { cmd: "chat.send_message", payload: "..." }
  2. GateSvr → ZoneSvr :Gate 将请求通过 gRPC 转发到 Zone 的 HandleClientRequest
  3. ZoneSvr 分发 :根据 cmd 前缀(如 auth.、chat.、friend.)选择对应的 System
  4. System → 后端服务:System 不实现业务逻辑,仅作为 RPC 转发层,调用 AuthSvr、ChatSvr 等
  5. 后端服务处理:执行真正的业务逻辑并访问 Store(如 RocksDB)
  6. 原路返回:结果沿 Zone → Gate → Client 返回

可以把 Gate 理解为「前台」,Zone 是「调度中心」,System 是「接线员」,后端 Svr 才是「办事的科室」。客户端只和前台打交道,前台把事交给调度中心,调度中心再转给对应的科室处理。


三、Zone-System 模式:为何需要「中间一层」

如果客户端直接连各个业务服务,会面临鉴权、路由、限流分散在各处、难以统一管理的问题。SwiftChatSystem 采用 Zone-System 模式 ,让 ZoneSvr 成为唯一业务入口:
ZoneSvr(API Gateway)
System 层(仅 RPC 转发)
HandleClientRequest
gRPC
gRPC
gRPC
gRPC
gRPC
gRPC
SystemManager
SessionStore
AuthSystem
ChatSystem
FriendSystem
GroupSystem
FileSystem
GateSvr
AuthSvr
OnlineSvr
ChatSvr
FriendSvr
FileSvr

核心约定:

  • System 只做转发:不写业务逻辑,不直接访问数据库
  • 实际逻辑在后端:AuthSvr、ChatSvr 等负责存储与业务规则
  • SessionStore 在 Zone:用于记录「谁连在哪个 Gate」,方便消息路由

这样带来的好处是:鉴权、限流、日志可以集中在 Zone;后端服务可以独立扩容;业务变更只需改后端,Zone 和 System 保持稳定。

SystemManager 的职责在代码中有明确注释:

cpp 复制代码
/**
 * 架构说明(API Gateway 模式):
 *
 *   GateSvr
 *      │
 *      ▼
 *   ZoneSvr (统一入口)
 *      │
 *      ├── AuthSystem ──(RPC)──→ AuthSvr (实际逻辑)
 *      ├── ChatSystem ──(RPC)──→ ChatSvr (实际逻辑)
 *      ├── FriendSystem ──(RPC)──→ FriendSvr (实际逻辑)
 *      ├── GroupSystem ──(RPC)──→ ChatSvr/GroupService
 *      └── FileSystem ──(RPC)──→ FileSvr (实际逻辑)
 *
 * System 只负责 RPC 转发,实际业务逻辑在后端服务中实现。
 */

四、七个后端服务及其职责

服务 端口 职责简述
GateSvr WS 9090 / gRPC 9091 WebSocket 连接管理、协议解析、心跳、将请求转发到 Zone
ZoneSvr gRPC 9092 统一入口、cmd 分发、在线状态与消息路由
AuthSvr gRPC 9094 注册、密码校验(VerifyCredentials)、用户资料(GetProfile / UpdateProfile)
OnlineSvr gRPC 9095 登录会话、JWT 签发、ValidateToken、单设备策略
FriendSvr gRPC 9096 好友关系、分组、黑名单
ChatSvr gRPC 9098 消息收发、群组、离线队列、@ 提醒、已读回执
FileSvr gRPC 9100 / HTTP 8080 文件元数据、分块上传、HTTP 下载

认证链路说明:AuthSvr 负责「你是谁」(身份与资料),OnlineSvr 负责「你已登录」(会话与 Token)。登录流程是:先调 AuthSvr.VerifyCredentials 校验账号密码,再调 OnlineSvr.Login 获取 JWT。


五、三层结构:Handler → Service → Store

各业务服务(AuthSvr、ChatSvr 等)内部采用统一的分层结构:无独立 API 层,Handler 直接实现 gRPC 接口。
Store 层(数据持久化)
Service 层(业务逻辑)
Handler 层(对外 API)
实现 proto 定义的 gRPC Service

解析请求、组装响应
注册、登录、消息收发等

调用 Store 读写数据
RocksDB / MySQL / Redis 读写

以 AuthSvr 为例,各层职责如下:

1. Handler 层:对接 gRPC,转发到 Service

cpp 复制代码
/**
 * 对外 API 层(Handler)
 * 直接实现 proto 定义的 gRPC AuthService
 * 接口:Register、VerifyCredentials、GetProfile、UpdateProfile。
 */
class AuthHandler : public AuthService::Service {
public:
  AuthHandler(std::shared_ptr<AuthServiceCore> service,
              const std::string& jwt_secret);

  ::grpc::Status Register(::grpc::ServerContext* context,
                          const RegisterRequest* request,
                          RegisterResponse* response) override;
  ::grpc::Status VerifyCredentials(...) override;
  ::grpc::Status GetProfile(...) override;
  ::grpc::Status UpdateProfile(...) override;

private:
  std::shared_ptr<AuthServiceCore> service_;
  std::string jwt_secret_;
};

2. Service 层:实现业务逻辑,调用 Store

cpp 复制代码
/**
 * 认证服务业务逻辑(身份 + 资料;登录/登出/Token 统一走 OnlineSvr)
 */
class AuthServiceCore {
public:
  explicit AuthServiceCore(std::shared_ptr<UserStore> store);

  RegisterResult Register(const std::string& username,
                          const std::string& password,
                          const std::string& nickname, ...);
  VerifyCredentialsResult VerifyCredentials(const std::string& username,
                                            const std::string& password);
  std::optional<AuthProfile> GetProfile(const std::string& user_id);
  UpdateProfileResult UpdateProfile(const std::string& user_id, ...);

private:
  std::shared_ptr<UserStore> store_;
};

3. Store 层:抽象存储接口,提供 RocksDB 实现

cpp 复制代码
/**
 * 用户存储接口
 * RocksDB Key 设计:
 *   user:{user_id}       -> UserData (JSON)
 *   username:{username}  -> user_id (用于登录查询)
 */
class UserStore {
public:
  virtual bool Create(const UserData& user) = 0;
  virtual std::optional<UserData> GetById(const std::string& user_id) = 0;
  virtual std::optional<UserData> GetByUsername(const std::string& username) = 0;
  virtual bool Update(const UserData& user) = 0;
  virtual bool UsernameExists(const std::string& username) = 0;
};

class RocksDBUserStore : public UserStore { /* ... */ };

Handler 只做「收包 → 调 Service → 填 response」,不关心存储细节;Service 只依赖 Store 接口,可随时切换实现(如从 RocksDB 迁到 MySQL)。


六、技术选型详解

下表汇总项目中用到的主要技术,并说明各自的职责与选型考量。

技术 在项目中的职责 选型考量
C++17 后端全部服务的实现语言 兼顾性能与开发效率;std::optional、std::shared_ptr 等现代特性简化业务代码;与 gRPC、RocksDB 等 C++ 生态天然兼容
gRPC + Protobuf 服务间 RPC 通信与接口定义 强类型、代码生成减少手写序列化;HTTP/2 多路复用,适合高并发;与 WebSocket 配合:客户端用 WS,后端内部用 gRPC
Protobuf(二进制) 客户端与 Gate 之间的消息编码 体积小、解析快,与后端协议统一;便于后续扩展字段而不破坏兼容
Boost.Beast GateSvr 的 WebSocket 实现 基于 Asio 的异步 I/O,与 C++ 生态一致;功能完善、文档丰富;无需引入额外语言运行时
RocksDB 用户、会话、消息、好友、文件元数据等持久化 嵌入式 KV,无需单独部署 DB 进程,开发/演示友好;支持 WriteBatch 原子写、前缀迭代;后续可渐进迁移到 MySQL,Store 接口保持不变
Redis(集群模式) ZoneSvr 的 SessionStore、Gate 注册、离线队列 支持多 Zone 副本共享会话状态;天然支持 TTL、List 等结构;单机开发可先用内存实现替代
AsyncLogger 各服务的日志输出 自研异步日志:双缓冲 + 后台线程刷盘,不阻塞业务;可独立复用至其他 C++ 项目;无网络开销,部署简单
JWT(HS256) 登录态凭证的签发与校验 无状态、易水平扩展;OnlineSvr 签发,业务服务本地验签即可,无需每次查库;HS256 对单机/小规模足够,大规模可考虑 RS256
nlohmann/json Store 层数据序列化(UserData、MessageData 等) 头文件库,集成简单;与 Protobuf 分工:RPC 用 proto,存储用 JSON 便于人工排查
OpenSSL JWT 签名、密码哈希等加解密 业界标准,系统或 vcpkg 易获取;用于 HMAC-SHA256、密码哈希等基础能力
CMake + vcpkg 构建系统与依赖管理 CMake 跨平台;vcpkg 统一管理 grpc、protobuf、rocksdb、boost 等,避免手动编译
Docker 单机与多机部署 镜像封装运行时,环境一致;Compose 一键拉起多服务,便于演示与交付
Kubernetes(Minikube) 集群部署与多副本编排 模拟生产环境;支持多 Gate/Zone 副本、Headless Service 做 gRPC 负载均衡;为后续 HPA、监控等预留
KeyValue Config(.conf + 环境变量) 各服务配置加载 配置与代码分离;环境变量覆盖便于容器注入敏感项(如 jwt_secret);key=value 格式简单易读

补充说明:

  • 为何用 WebSocket 而非 HTTP 轮询? 实时消息需要服务端主动推送,WebSocket 长连接天然支持双向通信,减少轮询带来的延迟与开销。
  • 为何拆 AuthSvr 与 OnlineSvr? 身份(注册、密码、资料)与会话(登录、Token、单设备)职责不同,拆分后各自可独立扩容与演进。
  • 为何 Store 用接口抽象? 便于从 RocksDB 迁移到 MySQL/Redis,业务层无需改动,只需替换 Store 实现。

七、小结

SwiftChatSystem 的整体架构可以归纳为:

  1. Gate → Zone → System → 后端 gRPC:请求链路清晰,职责边界明确
  2. Zone-System 模式:统一入口、按 cmd 分发,System 仅做 RPC 转发
  3. 七服务分工:Gate 接入、Zone 路由、Auth/Online 认证、Friend/Chat/File 业务
  4. Handler → Service → Store:业务服务内分层统一,便于扩展与替换实现

后续博客将分别深入 Protobuf 协议、配置与公共库、GateSvr、ZoneSvr 以及各业务服务的实现细节,敬请期待。

相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
weilx12344 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
Smileyqp沛沛4 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·4 天前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁4 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法