CHAPTER 01
架构与面试讲解
本文档用于面试场景,目标是帮助你在 5~15 分钟内清晰讲解项目的整体设计、核心模块实现细节、可被深挖的问题、与 Go + Gin 的差异以及改进方向。
1. 项目定位与设计目标
c++Server 是一个轻量级 C++ HTTP 服务框架,当前具备:
- HTTP 服务接入与请求分发
- 路由与中间件机制
- 请求解析(query/form/json/multipart)
- 响应构建(json/text/file/fileStream)
- 线程池并发模型
- 协程与调度器基础设施(跨平台)
- MySQL / Redis 连接器
- JWT 与密码哈希
- 基础日志与崩溃处理
项目特点是“底层可控、模块化清晰、可跨平台”,但在工业化能力(连接池、可观测性、协议完备性)上仍有演进空间。
2. 总体架构分层
2.1 分层视图
-
接入层(Network / HTTP)
- 监听端口、accept 连接、读取请求、解析协议、回写响应
- 关键实现:
src/Server.cpp、include/Server.h
-
并发调度层(ThreadPool / Coroutine)
- 线程池并发执行连接任务
- 协程与调度器提供用户态协作式调度能力
- 关键实现:
src/Threadpool.cpp、include/Coroutine.h、src/Coroutine.cpp
-
路由与处理层(Router / Handler / Middleware)
- method + path 路由命中
- 全局与路由级 middleware 链
- handler 负责业务逻辑并填充
Response - 关键实现:
src/route.cpp、src/handlers/common_handler.cpp
-
基础设施层(JSON / DB / Redis / JWT / Config / Log)
- JSON 解析序列化、MySQL/Redis 操作、鉴权与加密、日志、配置
- 关键实现:
include/JsonValue.h、include/DBConnector.h、include/RDConnector.h、include/jwt.h、include/ApiSender.h
2.2 依赖关系(简版)
main->Server+registerRoutesServer->ThreadPoolServer::parseRequest->Request::parseBody->JsonValuehandler->Response- 业务侧可调用
DBConnector/RdConnector/JWT/ApiSender Server/Response/ 其他模块 ->Log
3. 请求处理主链路(面试必背)
3.1 启动阶段
main.cpp中创建Server实例- 调用
registerRoutes(app)注册路由 app.run()进入监听循环
3.2 运行阶段(核心流程)
Server::run()创建监听 socket(IPv4/IPv6)accept()获取客户端连接- 将连接处理函数投递到线程池:
threadpool_.addTask(&Server::handleClient, ...) handleClient()从 socket 读取请求数据:- 先读取并解析 header
- 从
Content-Length得到 body 长度,继续读取 body
parseRequest()解析请求行、header、queryrequest.parseBody()按Content-Type解析 body- 执行 middleware 链(全局 + 路由级)
findRoute(method, path)命中 handler 并执行buildResponse(response)构建 HTTP 报文并send- 关闭连接或结束处理
3.3 请求数据结构
Request 关键字段:
method,path,headers,bodyqueryParamsbodyParamsjsonBodyuploadedFiles
Response 关键字段:
statusCode,headers,bodystreamWriter(用于大文件流式输出)
4. 核心模块细节
4.1 协程与调度器模块(Coroutine / Scheduler)
职责
- 提供用户态协程上下文切换
- 提供任务提交、工作窃取、时间片抢占基础能力
- 跨平台实现(Linux
ucontext,Windows Fiber)
关键类型与函数
Coroutineresume()suspend()state()
Schedulersubmit()/go()start()/stop()run_on_worker_thread()configureTimeSlice()shouldPreempt()
yield()/yield_now()
当前状态(面试建议说法)
- 协程基础设施完整,支持平台差异封装与调度队列。
- 但在 HTTP 主链路中仍以线程池同步处理为主,协程尚未全面承载 I/O 处理链路。
4.2 线程池模块(ThreadPool)
职责
- 管理 worker 线程
- 提供线程安全任务队列
- 支撑连接并发处理和异步任务执行
关键实现点
maxTasks_ = 10000:限制队列长度,防止无限堆积addTask():线程安全入队,支持可变参数绑定- worker 循环:
cv_.wait -> pop task -> execute
面试可讲的权衡
- 优点:实现稳定、易理解、适合快速搭建服务并发框架
- 不足:阻塞 I/O 场景下线程开销较大;队列满时拒绝策略较基础
4.3 服务器模块(Server)
职责
- 网络接入(监听、accept)
- HTTP 请求解析
- 路由与 middleware 执行
- 响应报文构建与发送
关键函数
run()handleClient()/handleClientIPv6()parseRequest()findRoute()buildResponse()addRoute(),get/post/put/del()use()(全局中间件)
请求解析支持
- Query 参数
application/x-www-form-urlencodedapplication/jsonmultipart/form-data(含文件)text/plain/xml/ 自动类型检测
响应能力
json()/text()/success()/error()file():整文件加载响应fileStream():分块流式输出(更适合大文件)
4.4 路由与中间件模块
路由机制
- 核心结构是
method -> path -> RouteEntry - 路径匹配当前为精确匹配
- 支持
RouterGroup前缀分组
Middleware 机制
- 类型:
std::function<bool(const Request&, Response&)> - 执行链:全局 middleware -> 路由 middleware -> handler
- middleware 返回
false时可中断后续执行
当前业务路由
- 根路径(GET/POST)
- 文件下载接口(普通下载 + 流式下载)
4.5 JSON 模块(JsonValue)
职责
- 提供 JSON 数据模型(null/string/number/bool/object/array)
- 支持 JSON 字符串解析与序列化
关键能力
fromJson()toJson()- 递归解析:
parseValue()parseObject()parseArray()parseString()
实现特征
- 手写递归下降解析,兼容常见 JSON 语法
- 支持转义字符与基础数值格式
面试要点
- 优势:可控、无外部依赖、便于按需扩展
- 风险:复杂 JSON 边界、深层嵌套、性能与成熟库仍有差距
4.6 数据库模块(DBConnector / Model)
职责
- MySQL 连接管理
- SQL 查询与执行封装
- 错误信息记录
关键函数
DBConnector::initInstance()DBConnector::getInstance()connect()query()execute()escapeSqlLiteral()
设计现状
- 单例模式管理连接参数与连接句柄
- 提供通用二维结果结构(
vector<map<string,string>>)
面试风险点
- 当前偏“单连接模型”,高并发下扩展性与线程安全策略需加强
- 缺少连接池、超时分级、重试策略、事务抽象层
4.7 Redis 模块(RdConnector)
职责
- Redis 连接管理与基础 KV 操作
关键函数
connect()get()set()/set(..., expireSeconds)exists()del()getError()
面试要点
- 已覆盖常见缓存基础能力
- 工业化增强方向:连接池、超时重试、pipeline、集群/哨兵支持
4.8 API 发送模块(ApiSender)
职责
- 向外部 HTTP API 发起请求(同步/异步)
- 支持 GET/POST/PUT/DELETE/PATCH
- 支持回调
关键接口
request()(异步通用)requestSync()(同步)get/post/put/del/patch()doRequest()(底层执行)
实现特征
- 内部可用线程池执行异步任务
- 封装
ApiResponse { statusCode, body, error, success }
4.9 加密与鉴权模块(JWT)
职责
- JWT 令牌生成与校验(HS256)
- claims 解析
- 密码哈希与验证
关键接口
generateToken()verifyToken()parseClaims()encrypt_password()verify_password()
安全实现点
- 包含
constant_time_compare(常量时间比较) - 支持默认 TTL 与自定义 claims
面试建议
- 明确说明令牌生命周期管理、密钥加载方式、过期校验策略
- 说明后续可接入更成熟安全库与密钥管理方案
4.10 配置、日志、稳定性模块
配置
Config+YamlParser用于读取配置项- 面试可强调“配置化替代硬编码”思路
日志
Log提供基础文件日志写入- 当前适合基础排障,后续可升级为结构化日志与分级日志
稳定性
CrashHandler负责崩溃兜底与异常场景处理- 可作为“工程可靠性意识”的加分点
5. 关键时序图(文字版)
- Client 发送 HTTP 请求到 Server
- Server 接受连接并投递线程池任务
- Worker 线程执行
handleClient - 解析 header/body,构建
Request - 执行 middleware 链
- 路由匹配并执行 handler
- handler 访问 DB/Redis/JWT/Json 等模块
- 构建
Response并回写 socket - 记录日志并结束连接处理
6. 面试高频深挖点(按优先级)
- 并发模型:为何采用线程池?协程为何未完全接管主链路?
- HTTP 兼容性:
Content-Length处理、长连接策略、边界条件与异常包处理 - 路由能力:精确匹配 vs 参数路由,如何扩展 REST 友好能力
- 数据库与缓存:单连接模型在高并发场景的问题与演进路径
- 安全性:JWT 签名校验、密码哈希、下载接口路径安全
- 可观测性:如何定位慢请求、错误高峰、资源瓶颈
- 跨平台设计:Windows/Linux 差异抽象与维护成本
7. 与 Go + Gin 的对比(面试表达模板)
当前项目优势
- 对底层网络与并发策略可控
- C++ 生态下便于做高性能定制
- 可作为“从 0 到 1 搭建服务器核心”的工程能力证明
相对不足
- 协程与 I/O 尚未完全协同
- DB/Redis 缺连接池与成熟治理能力
- 路由、中间件生态能力弱于 Gin
- 可观测性与运维链路未形成完整闭环
一句话总结
“Go + Gin 在工业化能力上开箱即用更成熟;本项目的价值在于底层机制可控与可深度定制,但需要继续补齐池化、可观测、协议完备性等能力。”
8. 改进路线图(可直接回答‘下一步怎么做’)
短期(1周)
- 配置全面接入启动流程(端口、DB、Redis、JWT)
- 增加健康检查与统一错误响应
- 增强日志字段(request_id、latency、status)
中期(1个月)
- MySQL/Redis 连接池化与超时重试机制
- 补参数路由、统一上下文对象、标准中间件链
- 压测基线与回归指标(QPS/P95/P99)
长期(1季度)
- 事件驱动 I/O(epoll/IOCP)与协程协同
- Metrics + Tracing + 集中日志完整可观测体系
- 容器化部署与发布治理(探针、滚动发布、回滚)
9. 面试速背版(30秒)
“这个项目是一个 C++ 轻量 HTTP 服务框架,分接入层、并发调度层、路由处理层和基础设施层。主链路是 accept -> 线程池 -> 请求解析 -> middleware -> handler -> 响应回写。我重点做了协程调度、线程池、JSON 解析、DB/Redis 接入、JWT 认证这些基础能力。当前优势是底层机制可控,短板是连接池、可观测和协议完备性,我的改进方案是短期配置化和健康检查,中期池化和中间件标准化,长期把事件驱动 I/O 与协程打通并完善运维体系。”