秒杀系统高并发优化实战(C++ / Drogon):1.2 为什么是 Drogon——C++ 框架横评与工业界的真实选择
上一篇 1.1 里我用五句话交代了"为什么选 Drogon",但那五句太像宣传册了。真到了面试或者技术评审上,一定会有人追问一句:"工业界到底谁在用 Drogon?"
这个问题很扎心,而且必须正面回答。这篇文章就干三件事:把 Drogon 和它的同类放到一张桌子上比,把"工业界实际用什么"讲清楚,最后交代我在这个项目上做这个选型时放弃了什么。
一、先回答最扎心的那个问题:工业界真用 Drogon 吗?
诚实答案分三层。
第一层:大厂的 C++ 后端,几乎不使用"Web 框架"这个词。 你去问百度、腾讯、字节的 C++ 团队用什么,答案不会是 Drogon,也不会是 oat++,而是 RPC 框架——brpc、Sogou Workflow(及其上的 SRPC)、TARS、gRPC。原因很简单:大厂内部服务之间走的是二进制协议 + 服务发现,HTTP 只是南北向入口那一层,而入口通常由 Nginx / OpenResty / Envoy / Go 网关承担,轮不到 C++ 业务服务直接对公网。
第二层:Drogon 是"社区里最好的 C++ Web 框架",不是"大厂标配"。 这两件事不矛盾。Drogon 在 GitHub 上是 C++ Web 框架里星标最高的那一档,TechEmpower Round 19(2020-05)综合榜拿过第一,Round 21 综合分 7801 排在所有框架之首(同期 Rust actix 7667、ASP.NET Core 7077、Go gin 1943、Spring 1846)。但这只能证明它跑得快、功能全,不能证明大厂在生产用它。它的真实用户画像是:个人项目、创业公司、边缘/嵌入式 Linux 上的 HTTP 服务、以及需要 C++ 性能又不想自己拼装全家桶的小团队。
第三层:真正被生产验证的 C++ 通信框架,都有公开的落地清单。 举两个我查得到出处的:
| 框架 | 落地规模(公开资料) |
|---|---|
brpc(百度开源,2022-12 从 Apache 孵化器毕业成 TLP) |
百度内部 4000+ 活跃模块、600 万+ 实例;小红书推荐 1 万+ 实例;爱奇艺广告 3000+ 台机器;vivo、滴滴、B站、作业帮、欢聚时代、第四范式等均有落地;Apache Doris / BaikalDB / StarRocks 用它做节点间 RPC |
Sogou C++ Workflow |
支撑搜狗几乎所有 C++ 后端在线服务(搜索、云输入法、在线广告),日处理请求百亿级;官方压测小包(64/512 B)可稳定在 50 万 QPS |
注意这两位都不是"Web 框架":brpc 是 RPC 框架,Workflow 是"通信 + 计算"一体的任务流引擎。它们的共同点是内部服务通信,不是"给你一个 HTTP 路由 + ORM + 模板引擎让你写业务"。
本质一句话:
C++在工业界的主战场是基础设施(存储、检索引擎、推荐、广告、音视频、游戏服务端),那里的关键词是RPC和延迟;而"用C++写对外HTTP业务后端"本身就是小众选择,Drogon是这个小众赛道里最好的那一个 🐾。
二、把赛道分清楚:Web 框架 / RPC 框架 / 网络库,别跨赛道比
技术选型文章最常见的错误,就是把 Drogon 和 brpc 拉到一起比"谁更强"。它们解决的不是同一个问题。先把赛道画出来:
把这张表压成文字版:
| 框架 | 赛道 | 并发模型 | 内置件 | 谁在生产用 | 最适合的场景 |
|---|---|---|---|---|---|
Drogon |
Web 全家桶 |
epoll/kqueue + 回调 / C++20 协程 |
ORM(PG/MySQL/SQLite)、Redis 客户端、WebSocket、HTTP/2、Session、模板 |
社区、创业公司、边缘设备 | 想用 C++ 写完整 HTTP 服务,且不想拼装十个库 |
oat++ |
Web(零依赖) |
自研异步 API |
ORM 模块化、Swagger/OpenAPI、WebSocket |
IoT / 嵌入式 / 受限环境 |
二进制体积和依赖数量是硬约束 |
userver |
Web / 微服务 |
异步 + 组件模型 | PG / Mongo / Redis / ClickHouse 驱动、完善的测试与可观测工具 |
Yandex 内部大量生产服务 |
C++ 微服务,且团队愿意接受它的组件范式 |
Crow |
Web 微框架 |
同步/半异步(无协程) | 只有路由 + JSON |
原型、教学 | 半天搭个 demo,别指望生产 |
Pistache |
Web 微框架 |
异步 | 路由 + REST 语义 |
少量自用 | 想要干净的 C++11 REST API |
brpc |
RPC |
bthread(M:N 用户态线程) |
多协议、bvar 监控、内置调试服务 |
百度 / 小红书 / 爱奇艺 / vivo / 滴滴 / B站… |
内部服务间高性能调用,要治理要可观测 |
Sogou Workflow |
通信+计算引擎 | 异步任务流 | HTTP/Redis/MySQL/Kafka 异步客户端、DAG 调度 |
搜狗全站 | 一个进程里要编排复杂异步依赖 |
Boost.Asio / muduo |
网络库 | proactor / reactor |
什么都没有 | 自研框架的地基 | 想自己造轮子、或者要极致可控 |
看清这张表,很多争论就没意义了:拿 brpc 和 Drogon 比"谁更适合写 HTTP 接口",就像拿变速箱和整车比谁更能跑。
三、那这个项目为什么选 Drogon:六条硬理由,每条都带代价
我给这个项目定的目标是"把一个秒杀系统从 400 QPS 一路优化到万级,并把每一层的取舍讲透"。在这个目标下,选型的判据不是"哪个最工业",而是**"哪个把我的精力留在架构上,而不是消耗在胶水代码上"**。
理由一:它把地基活一次性干完了。 HTTP 服务、ORM、Redis 客户端、WebSocket、Session、JSON 全内置。换成 Crow 或 Pistache,我得自己接 MySQL 客户端、自己包 hiredis、自己写连接池——主线会从我真正想讲的"行锁竞争 / 缓存一致性 / MQ 削峰"漂移成"如何集成七个第三方库"。
代价:全家桶意味着框架偏"重",它要拥有
main()和事件循环,想和别的框架共存很难(不像Poco、Pistache那样可以只取一部分用)。
理由二:异步是内核级的,不是外挂的。 Drogon 的网络层是自带的 trantor:每个 IO 线程一个 EventLoop,连接 accept 后绑定到某个 EventLoop,后续读写回调都在那一个线程内执行——天然免锁。数据库和 Redis 客户端同样异步,回调统一派发回 EventLoop 线程。
这一条对本项目是决定性的。配置里 threads_num=4,也就是只有 4 个 IO 线程;如果 MySQL 客户端是同步的,一次 DB 往返就会把该线程上排队的请求全部卡住,4 线程直接变成 4 并发。实测阶段一干净态基线约 440 QPS,排查下来瓶颈完全在 MySQL 行锁串行化上(每个请求占一条连接、并持 seckill_sku 行锁直到事务提交),框架层没有成为瓶颈——这正是我要的:让瓶颈暴露在架构层,而不是被框架的实现方式掩盖。
理由三:内置 ORM 的异步事务语义。 秒杀下单的"扣库存 + 落订单"必须在同一个事务里,Drogon 的 Transaction 给了这个能力。下面是项目里真实在跑的写法(Drogon 1.9.10 回调式,节选):
1 | // src/service/SeckillService.cc(节选,省略异常回调与日志) |
用 Crow 这类"只有路由"的框架,这套异步事务语义得自己基于 MySQL C API 实现一遍。
顺带说一句:token(4.8 应用层在途闸门的标记)被按值捕获进每一层 lambda,这不是啰嗦——只捕获进最外层的话,最外层 lambda 发起第一条 SQL 后就析构了,标记会被提前清掉,闸门形同虚设。异步框架里的资源生命周期,全靠 shared_ptr 的析构时机来兜。
理由四:内置 Redis 客户端是异步的,这一点在登录模块救了命。 我最初规划的是 redis-plus-plus,落地时换成了 Drogon 内置的 nosql::RedisClient(底层 hiredis)。原因很硬:redis-plus-plus 是同步 API,而我们的 handler 跑在 IO 线程上,同步等一次 Redis 往返会阻塞整个线程上的排队请求——这是结构性缺陷,不是调优能解决的。内置客户端异步、与事件循环同构,且零额外依赖(只需 libhiredis-dev)。
理由五:性能天花板足够高,不会反过来成为我要优化的对象。 TechEmpower Round 19 综合榜第一;Round 21 综合分 7801 居首;Fortunes 场景(带 ORM + 模板渲染,最接近真实业务)drogon-core 长期在百万 rps 量级;官方口径是 Ryzen 3700X 单核 > 15 万 req/s。我要练的是架构优化,不希望中途发现"框架本身就是天花板"。
理由六:工程约束——两条 cmake 命令能构建。 这个项目要跟着文章一起发布,读者能复现是硬指标。drogon_ctl 一键生成脚手架,依赖用 apt 装齐,cmake .. && make 就完事。如果为了引入某个库需要 FetchContent 从 GitHub 拉源码(我在 JWT 选型上正是因此放弃 jwt-cpp、改为自实现 HS256),在 WSL 网络环境下就多一个损坏点。
最关键的代价:
Drogon不提供任何服务治理件——没有分布式锁、没有限流、没有注册中心、没有熔断。Java那边Redisson/Sentinel/Nacos开箱即用,这里全部得自己写。但对这个项目来说这不是缺点而是设计意图:阶段四"自实现治理"本来就是我要练的东西。反过来说,如果你要做的是交付周期紧张的生产系统,这条会直接劝退。
四、诚实地讲 Drogon 的短板
选型论证如果只讲优点,就是广告。下面这些是真实的代价,我也确实被它们绊过:
| 短板 | 具体表现 | 我在项目里怎么应对 |
|---|---|---|
| 生态薄 | C++ Web 框架整体都是小众赛道,Drogon 已是星标最高的那档,但和 Spring / Gin 完全不是一个量级;第三方中间件集成要自己写 |
只依赖框架核心能力,业务逻辑尽量不绑框架特性 |
| 治理件为零 | 分布式锁 / 限流 / 注册配置 / 熔断,一个都没有 | 全部自实现(阶段四主线),Redis SET NX + Lua 打底 |
| 回调与协程双模式并存 | 历史包袱:早期 API 是回调式,新版加协程。1.9.10 的 Transaction 连 commit() 成员都没有——提交靠"最后一个 shared_ptr<Transaction> 析构"自动触发,rollback() 置标志阻止自动提交;且流式 << / >> 不支持 (Result, exception_ptr) 合并回调,每条 SQL 只能用 execSqlAsync(sql, 成功回调, 异常回调, 参数...)。开 C++20 协程的新版才回到 co_await 形态 |
钉死 Drogon 1.9.x 回调式写法(见项目 ADR-5),升级协程版时统一改写 |
| 文档与社区响应 | 中文资料相对多,但深度问题基本靠读源码 | 关键实现(如取客户端 IP)直接翻 HttpRequest.h 确认 |
| 单机框架 | 不带服务发现、配置中心、链路追踪 | 阶段四用 brpc + etcd 补 |
| 招人难 | 团队里没人会就得自己扛,且 C++ 开发者价格高、供给少 |
这个项目的定位是个人技术实践,不是团队协作产品 |
其中第三和第四条我都踩过实坑。举个具体的:Drogon 1.9.10 的 HttpRequest 只有 getPeerAddr(),没有 getClientIp() 也没有 getRealIp()——框架不内建"从 X-Forwarded-For 解析真实客户端 IP"的能力。我按直觉写了 req->getClientIp(),编译直接挂,翻官方头文件才确认得自己解析请求头。这是小众框架最典型的风险:没有足够的博客告诉你坑在哪,你得自己去读源码。
五、那"实际工作中该用什么框架"?
这才是问题里最有价值的一半。我的判断规则很简单——先看你在写什么,再看 C++ 是不是这个场景的正确语言:
对应到具体岗位和场景:
| 场景 | 该用什么 | 为什么 |
|---|---|---|
| 电商 / 金融 / 中后台业务系统 | Java(Spring Boot + 全家桶) |
中间件生态 100% 覆盖、招人容易、十年可维护 |
云原生基础设施、API 网关、IM 长连接 |
Go(gin / go-zero / Kratos) |
goroutine 模型 + 单二进制部署,人效与性能的甜点 |
| 存储引擎、检索引擎、推荐 / 广告、特征服务 | C++ + brpc / Workflow / TARS |
延迟与内存可控,且有工业级验证(brpc 在百度 600 万+ 实例) |
| 游戏服务端 / 音视频 / 高频交易 | C++ + 自研或 Asio 生态 |
GC 停顿不可接受,需要精细控制内存布局 |
嵌入式 / IoT 设备上的 HTTP 服务 |
oat++ |
零外部依赖、二进制体积可压到 MB 以下 |
需要 C++ 性能、又要快速出 HTTP 服务的中小项目 |
Drogon |
全家桶最全、性能天花板最高、社区最大 |
| 学习 / 面试用的练手项目 | Drogon(想讲架构)或 muduo 自研(想讲底层) |
前者让你专注架构,后者让你吃透 epoll |
六、如果有人问你"工业界没人用 Drogon",怎么答
这是我给自己的标准答案,三层递进:
- 承认事实:对,大厂
C++后端的主力是brpc/Workflow/TARS这类RPC框架,C++的HTTP业务后端本身就是小众场景,Drogon不是大厂标配。 - 说清定位:
Drogon是"社区最好的C++Web框架"——TechEmpower综合榜拿过第一,功能完整度(ORM+Redis+WebSocket+HTTP/2)在同类里没有对手。用它不等于宣称它是工业标准。 - 回到目标:这个项目的目标是"把高并发架构的每一层优化讲透",不是"交付一个生产级电商系统"。
Drogon把HTTP/ORM/Redis的地基活干完,把架构层的取舍完整地留给我——实测基线 440QPS的瓶颈在MySQL行锁,不在框架,后续每一级跃迁(缓存 →MQ→Lua原子预扣)也都是架构收益,没有一级来自换框架。这恰恰证明选型是对的:我把力气花在了该花的地方。
本质一句话:选框架不是选"最强的那个",而是选**"把你的瓶颈留在你想练的地方"的那个**。
Drogon让我把 90% 的精力花在行锁、缓存一致性、削峰、原子扣减上,只有 10% 花在框架本身——这就是我选它的全部理由 🐾。
七、本项目里的实际取舍清单
最后把落到代码上的决策一次列清,方便对照源码:
| 决策 | 选择 | 放弃的 |
|---|---|---|
Redis 客户端 |
Drogon 内置 nosql::RedisClient(异步,hiredis 底层) |
redis-plus-plus(同步,会阻塞 IO 线程) |
JWT 签发 |
自实现 HS256(OpenSSL HMAC + base64url) |
jwt-cpp(需 FetchContent 拉 GitHub) |
ORM / 事务 |
Drogon 内置 DbClient 异步事务 |
mysql-connector-cpp / SOCI |
| 短信发送 | 自签发 / 日志模式,不接网关 | 腾讯云 API + libcurl + TC3 签名 |
| 版本与写法 | Drogon 1.9.x 回调式 ORM API |
C++20 协程版(API 语义会变,见 ADR-5) |
| 服务治理 | 全部自实现(Lua 原子限流 / 令牌桶 / 布隆) |
任何第三方治理库 |
| 前端 | 阶段四之前不做(ADR-4) |
Vue / Vite 构建链 |

