从零构建现代C++ Web服务器(六):数据库中间件与协程连接池

从零构建现代C++ Web服务器(六):数据库中间件与协程连接池 系列导航:第一篇:设计理念 | 第二篇:协程与内存池 | 第三篇:路由、中间件与SSL | 第四篇:实战与性能 | 第五篇:Cookie、Session与文件服务 | 第六篇:数据库中间件(本文) 前置知识 阅读过本系列前五篇(特别是第二篇的协程基础和第三篇的中间件洋葱模型) 了解 SQL 基础和 MySQL 数据库操作 了解连接池的基本概念 目录 1. Web 框架为什么需要数据库层 2. 架构总览:六层洋葱 3. 后端抽象:DbConnection 接口 4. MySQL 实现:any_connection 封装 5. LRU PreparedStatement 缓存 6. 协程连接池:用 steady_timer 做信号量 7. DB 中间件:请求级连接生命周期 8. 查询日志:装饰器模式的妙用 9. 综合实战:用户管理 API + 数据库 10. 总结 1. Web 框架为什么需要数据库层 前五篇构建了 hical 的完整 HTTP 骨架——协程驱动的异步 I/O、PMR 内存池、路由、中间件、SSL、Cookie/Session、静态文件。但现实中的 Web 服务几乎都绑定数据库:用户注册要写库、商品查询要读库、交易扣款要事务。 如果把数据库操作留给业务代码自行处理,会出现几个典型问题: 问题 后果 每个请求都新建连接 MySQL 握手 + 认证 ≈ 1-3ms,高并发下成为瓶颈 业务代码管理连接生命周期 忘记关闭 → 连接泄漏,异常时忘记回滚 → 数据不一致 手动拼接 SQL SQL 注入漏洞(游戏服务器的经济系统被注入 = 灾难) 同步 MySQL 客户端 mysql_query() 阻塞 io_context 线程 → 吞吐暴跌 hical v2.3.0 补齐了这最后一块拼图: ...

April 30, 2026 · 20 min · 4080 words

设计 Hical OpenAPI 模块的心得

设计 Hical OpenAPI 模块的心得 一、为什么要做这件事 Hical 框架从一开始就内建了两套反射基础设施:MetaJson(DTO 字段反射)和 MetaRoutes(路由反射)。这意味着框架在编译期就已经知道"每个结构体有哪些字段、叫什么名字、什么类型、是否必填"以及"每个 Handler 有哪些路由、什么方法、什么路径"。 这些信息恰好是生成 OpenAPI spec 所需要的全部输入。 在 C++ Web 框架领域,Drogon 通过插件支持 Swagger,Oat++ 有内建的 API 文档生成,但没有任何 C++ 框架能做到"从 C++20 宏反射层自动导出 OpenAPI 3.0 spec"这件事。这是 Hical 反射层设计的一个天然延伸,也是最有潜力的差异化卖点。 做之前我最担心的问题是:C++20 的宏回退路径能不能提取足够的类型信息来生成 JSON Schema?C++26 的 jsonSchema<T>() 可以用 std::meta::type_of(member) 直接获取字段类型,但 C++20 只有 FieldDescriptor<Class, FieldType> 的成员指针。后来发现,通过 decltype(std::declval<T>().*(field.pointer)) 在 fold expression 的每次展开中推导出具体的 FieldType,完全可以做到。这个验证结果让我决定动手。 二、架构决策 四层分离 最终的架构是四层设计: 1 2 3 4 Layer 4: OpenApiEndpoint.h — serveOpenApi() / Swagger UI Layer 3: OpenApiDocument.h/cpp — 文档组装 Layer 2: OpenApiRegistry.h/cpp — 路由元数据收集 + 标注宏 Layer 1: OpenApiSchema.h — JSON Schema 生成 这不是一开始就想好的。最初的想法是把所有东西塞进一个 OpenApi.h 里——Schema 生成、路由收集、文档组装、端点注册全放一起。但很快发现几个问题: ...

April 30, 2026 · 3 min · 533 words

搭建 Hical HTTP 服务器 — 多平台环境搭建指南

搭建 Hical HTTP 服务器 — 多平台环境搭建指南 概述 本文档涵盖 Hical v2.0.0 在所有支持平台上的环境搭建,包括三种安装方式(vcpkg / Conan / 源码编译)和五个平台(Windows MSYS2、Windows MSVC、Ubuntu/Debian、Fedora/Arch、macOS)。 依赖要求 组件 版本要求 用途 C++ 编译器 GCC 14+ / Clang 22+ / MSVC 2022+ C++20 协程 + C++26 反射(可选) CMake >= 3.20 构建系统 Boost >= 1.70 Asio / Beast / JSON / System OpenSSL 必需 SSL/TLS 支持 Google Test 必需 单元测试 安装方式一:vcpkg(推荐) vcpkg 是最简单的安装方式,一行命令自动解决所有依赖。 安装 vcpkg(如未安装) 1 2 3 git clone https://github.com/microsoft/vcpkg.git cd vcpkg && bootstrap-vcpkg.bat # Windows cd vcpkg && ./bootstrap-vcpkg.sh # Linux / macOS 将 vcpkg 目录加入 PATH,或记住安装路径用于后续 CMAKE_TOOLCHAIN_FILE。 ...

April 22, 2026 · 5 min · 1018 words

Hical 框架应用场景全景分析

Hical 是一个现代 C++ 高性能 Web 框架,基于 Boost.Asio/Beast,具备 PMR 内存池、协程异步 I/O、WebSocket、SSL/TLS、C++26 反射层等特性。本文覆盖游戏行业 + 通用行业的全部适用场景。 一、游戏行业场景(简要) 场景 说明 GM/运营后台 REST API + 静态页面 + Session 鉴权 支付/SDK 回调网关 高并发 HTTP 接入,协程非阻塞 WebSocket 实时服务 聊天、排行榜推送、GM 监控 内部微服务 HTTP 层 MetaJson/MetaRoutes 零样板代码 二、通用行业场景 1. IoT / 嵌入式设备管理后台 ⭐ 高匹配度 为什么适合: IoT 网关和嵌入式设备普遍用 C/C++ 开发,Hical 保持语言一致性 单二进制部署,无运行时依赖,适合资源受限环境(树莓派、工控机) PMR 内存池提供可预测的内存行为,避免 GC 抖动 WebSocket 双向通信天然适合设备状态实时推送 典型用例: 设备状态监控 Dashboard(HTTP + WebSocket 推送) 固件 OTA 更新接口(Multipart 文件上传) 传感器数据采集 HTTP 接口 边缘计算节点的本地 Web 管理界面 2. 高频交易 / 量化金融辅助服务 为什么适合: ...

April 13, 2026 · 2 min · 359 words

C++26 反射落地实战:双路线条件编译实现自动路由注册、JSON 序列化与 OpenAPI 文档生成

C++26 反射落地实战:双路线条件编译实现自动路由注册、JSON 序列化与 OpenAPI 文档生成 本文以 Hical 框架(v2.5)为例,展示如何在 C++26 反射尚未被主流编译器完全支持的现阶段,用"C++26 反射 + C++20 宏回退"的双路线策略,让用户享受相同的 API——从 JSON 序列化、路由注册到 OpenAPI 3.0 文档自动生成。 问题:Web 框架中的重复样板代码 每个 Web 框架都有三大类重复劳动: 1. 路由注册——每个处理函数都要手写一行注册: 1 2 3 4 5 6 router.get("/api/users", listUsers); router.get("/api/users/{id}", getUser); router.post("/api/users", createUser); router.put("/api/users/{id}", updateUser); router.del("/api/users/{id}", deleteUser); // ... 50 个路由 = 50 行手写注册 2. JSON 序列化——每个 DTO 都要手写字段映射: 1 2 3 4 json["name"] = user.name; json["age"] = user.age; json["email"] = user.email; // ... 10 个字段 = 10 行手写映射 3. API 文档——每个接口都要手写 OpenAPI 描述,且与代码脱节: ...

April 12, 2026 · 8 min · 1516 words

为 C++ Web 框架设计三层 PMR 内存池:从原理到实战

为 C++ Web 框架设计三层 PMR 内存池:从原理到实战 本文以 Hical 框架为例,深入讲解如何利用 C++17 PMR(Polymorphic Memory Resource)为高并发 Web 服务器构建三层内存池架构。 为什么 Web 服务器需要自定义内存管理? 一个 HTTP 请求的生命周期中,框架需要分配大量临时对象:解析缓冲区、路径字符串、JSON 值、响应体。在高并发场景下(如 50K QPS),new/delete 的全局锁竞争会成为显著瓶颈: 1 2 3 50,000 请求/秒 × 每请求 ~20 次分配 = 1,000,000 次/秒 new/delete ↓ 全局堆锁竞争 → CPU 空转 传统方案是自研内存池,但 C++17 提供了标准化的解决方案 —— PMR。 PMR 速览 PMR 的核心思想:把内存分配策略从容器类型中解耦。 1 2 3 4 5 // 传统方式:分配器绑定在类型中 std::vector<int> vec; // 永远用 std::allocator // PMR 方式:运行时切换分配策略 std::pmr::vector<int> vec(&myPool); // 用自定义内存池 标准库提供了三种现成的内存资源: ...

April 12, 2026 · 3 min · 438 words

从零构建现代C++ Web服务器(一):设计理念与架构总览

从零构建现代C++ Web服务器(一):设计理念与架构总览 系列导航:第一篇:设计理念(本文) | 第二篇:协程与内存池 | 第三篇:路由、中间件与SSL | 第四篇:实战与性能 | 第五篇:Cookie、Session与文件服务 | 第六篇:数据库中间件 前置知识 熟悉 C++17、C++20 基础语法(模板、智能指针、lambda、协程、Concepts) 了解 TCP/IP 和 HTTP 协议基本概念 对异步编程模型有初步认知 目录 1. 为什么在 2026 年用 C++ 写 Web 框架? 2. 现有方案分析 3. hical 的设计目标 4. 两层架构设计 5. C++20 Concepts 做后端抽象 6. 线程模型:1 Thread : 1 io_context 7. 全文总结 1. 为什么在 2026 年用 C++ 写 Web 框架? 当大多数团队选择 Go、Rust 或 Node.js 构建 Web 服务时,用 C++ 写 Web 框架似乎是"逆潮流而行"。但事实是,在特定场景下 C++ 仍然不可替代: 极致性能需求:游戏服务器、实时通信、高频交易等场景对延迟敏感到微秒级别 与现有 C++ 生态集成:当你的业务逻辑、数据处理库本身就是 C++ 时,跨语言调用引入的开销和复杂度不可忽视 内存可控:C++ 没有 GC 暂停,配合内存池可以实现完全可预测的内存行为 更重要的是,C++20/26 带来了一系列改变游戏规则的特性: ...

April 12, 2026 · 9 min · 1789 words

从零构建现代C++ Web服务器(三):路由、中间件与 SSL

从零构建现代C++ Web服务器(三):路由、中间件与 SSL 系列导航:第一篇:设计理念 | 第二篇:协程与内存池 | 第三篇:路由、中间件与SSL(本文) | 第四篇:实战与性能 | 第五篇:Cookie、Session与文件服务 | 第六篇:数据库中间件 前置知识 阅读过本系列前两篇(架构分层、协程基础、PMR 内存池) 了解 HTTP 请求/响应基本结构 了解中间件(Middleware)的概念(如 Express/Koa 的洋葱模型) 目录 1. 路由系统设计 2. 洋葱模型中间件管道 3. 模板化 SSL:编译期零开销 4. WebSocket 集成 5. 组装:HttpServer 门面 6. 总结 1. 路由系统设计 1.1 双策略路由:快速与灵活的平衡 Web 框架的路由系统需要处理两类路径: 静态路由:/api/status、/api/users — 路径固定,可以精确匹配 参数路由:/users/{id}、/posts/{pid}/comments/{cid} — 路径含变量,需要模式匹配 hical 采用双策略设计: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 请求到达: GET /api/users/42 │ ▼ ┌─────────────────────────────┐ │ 1. 静态路由查找 (O(1)) │ │ unordered_map 哈希表 │ │ 查找 {GET, "/api/users/42"} │ │ → 未命中 │ └───────────┬─────────────────┘ │ ▼ ┌─────────────────────────────┐ │ 2. 参数路由匹配 (线性扫描) │ │ 遍历 paramRoutes_: │ │ {GET, "/users/{id}"} │ │ → 匹配!提取 id = "42" │ └───────────┬─────────────────┘ │ ▼ 执行 handler 为什么不统一用 Trie 树?因为绝大多数实际应用中,静态路由占比远大于参数路由。用哈希表处理静态路由是 O(1),比 Trie 的 O(path_length) 更快。参数路由数量通常很少(几十个),线性扫描完全可以接受。 ...

April 12, 2026 · 13 min · 2702 words

从零构建现代C++ Web服务器(二):协程异步与 PMR 内存池

从零构建现代C++ Web服务器(二):协程异步与 PMR 内存池 系列导航:第一篇:设计理念 | 第二篇:协程与内存池(本文) | 第三篇:路由、中间件与SSL | 第四篇:实战与性能 | 第五篇:Cookie、Session与文件服务 | 第六篇:数据库中间件 前置知识 了解协程关键字(co_await、co_return、co_yield)的基本含义 理解智能指针和 RAII 模式 了解 std::pmr(Polymorphic Memory Resource)的基本概念 目录 从零构建现代C++ Web服务器(二):协程异步与 PMR 内存池 前置知识 目录 1. 从回调地狱到 co_await 1.1 传统回调方式 1.2 协程方式 1.3 协程的工作原理(简化) 2. Awaitable:hical 的协程基石 工具函数 3. 协程在框架中的实际应用 3.1 Accept 循环 3.2 HTTP 会话处理 3.3 协程执行全景 4. PMR 内存池:为什么默认 allocator 不够好 4.1 问题分析 4.2 Benchmark 对比 5. 三层内存架构深度剖析 5.1 教学代码:从零实现简化版三层 PMR 5.2 教学代码:三层管理器 5.3 generation 计数器的妙用 6. PmrBuffer:零拷贝缓冲区 6.1 设计思路 6.2 教学代码:简化版 PmrBuffer 6.3 makeSpace 策略图解 7. 协程 + PMR 协同 8. 总结 核心要点 下篇预告 1. 从回调地狱到 co_await 1.1 传统回调方式 假设我们要写一个 TCP Echo Server。传统的异步回调方式是这样的: ...

April 12, 2026 · 12 min · 2520 words

从零构建现代C++ Web服务器(五):Cookie、Session、静态文件与文件上传

从零构建现代C++ Web服务器(五):Cookie、Session、静态文件与文件上传 系列导航:第一篇:设计理念 | 第二篇:协程与内存池 | 第三篇:路由、中间件与SSL | 第四篇:实战与性能 | 第五篇:Cookie、Session与文件服务(本文) | 第六篇:数据库中间件 前置知识 阅读过本系列前四篇(特别是第三篇的中间件洋葱模型) 了解 HTTP Cookie 与 Session 基本概念 了解 multipart/form-data 编码格式基本原理 目录 1. Web 应用的"最后一公里" 2. Cookie:无状态协议的状态记忆 3. Session:从 Cookie 到有状态会话 4. 静态文件服务:安全地托管资源 5. Multipart 文件上传:解析 RFC 7578 6. 综合实战:带登录的文件管理服务 7. 全系列总结 1. Web 应用的"最后一公里" 经过前四篇的铺垫,hical 已经具备了完整的 HTTP 服务器骨架——协程驱动的异步 I/O、PMR 内存池、双策略路由、洋葱模型中间件、SSL/WebSocket 支持,以及反射宏系统。 但如果你真正尝试用它搭建一个 Web 应用,很快就会发现少了几样东西:用户登录后刷新页面状态丢失、无法提供前端静态资源、用户没法上传头像文件。这些功能看似"基础",却是 Web 应用从"能跑通"到"能用"的最后一公里。 hical v1.0.0 补齐了这四块拼图: 模块 解决的问题 集成方式 核心文件 Cookie HTTP 无状态协议下的客户端状态存储 req.cookie() / res.setCookie() Cookie.h HttpRequest.cpp HttpResponse.cpp Session 服务端有状态会话管理 makeSessionMiddleware() 中间件 Session.h Session.cpp StaticFiles 安全地托管前端/资源文件 serveStatic() 工厂函数 StaticFiles.h Multipart 文件上传(RFC 7578) MultipartParser::parse() 静态方法 Multipart.h Multipart.cpp 它们在 hical 整体架构中的位置: ...

April 12, 2026 · 20 min · 4181 words