回源缓存核心是选对协议栈与分层缓存策略,而非手写http服务器;需用evpp/brpc/nghttp2等成熟引擎,区分range请求统一key,brpc需禁用重试,淘汰策略须结合热度与ttl对齐。

回源缓存的核心不是“写个服务器”,而是选对协议栈和缓存策略
直接用 std::map 存视频切片、手写 HTTP 回源逻辑,撑不过 1000 并发。真正在 CDN 边缘节点跑的回源缓存服务,90% 以上依赖成熟 I/O 模型 + 零拷贝传输 + 分层缓存,C++ 只负责胶水和关键路径优化。你不需要从零实现 HTTP/1.1 或 TLS,而要决定用哪个底层引擎:evpp(基于 libevent)、brpc(百度 RPC 框架附带高性能 HTTP client/server)、或直接封装 nghttp2 + openssl 做 HTTP/2 回源。
常见错误是把“C++ 写服务器”等同于“自己 parse HTTP header”。实际线上节点几乎都复用 nginx 模块(如 ngx_http_upstream_module)或基于 envoy 扩展,C++ 代码只写 cache key 生成、鉴权回调、分片合并逻辑。
视频分片缓存必须区分 Range 请求与完整文件语义
直播场景下,客户端几乎全是 GET /live/abc.m3u8 或带 Range: bytes=1024-2047 的 ts/fmp4 请求。如果缓存层不识别 Range,会把每个不同 range 当作独立 key,导致缓存爆炸、磁盘碎片化。
- 缓存 key 必须剥离
Range参数,统一按完整资源路径(如/live/abc_0001.ts)计算,但后端存储需支持按 offset 读取 - 响应时检查原始请求是否含
Range:有则用sendfile()或splice()直接从文件 offset 复制;无则返回整个文件 +Content-Length - 注意
206 Partial Content的Content-Rangeheader 必须由缓存服务动态重写,不能透传上游
brpc 是目前最省心的 C++ 回源方案,但得关掉默认重试
brpc 内置连接池、超时控制、负载均衡和 HTTP/2 支持,比手撸 libcurl + epoll 稳定得多。但它默认对 5xx 错误重试 3 次 —— 对直播流来说,重试只会放大卡顿,必须禁用:
butil::FLAGS_max_retry = 0; // 同时设置单次超时:回源失败宁可 404 也不卡住 brpc::ChannelOptions options; options.timeout_ms = 3000; options.connect_timeout_ms = 1000;
另外,brpc 的 StreamInput 接口能边下载边上行,避免把整个 ts 文件读进内存再转发,这对 10MB+ 的 fMP4 分片很关键。
缓存淘汰不能只靠 LRU,得结合视频热度与过期时间
纯内存 LRU 对视频无效:一个 4K 直播流每秒产生 3–5 个 ts 分片,1 小时就是上万个文件,LRU 很快踢掉刚热起来的热门流。真实做法是分层:
- 内存层:用
rocksdb的Cache(非全量存储)缓存热点分片的元数据(size、mtime、etag) - 磁盘层:用
ext4+noatime,dir_index格式化,分片按md5(url)哈希到子目录,避免单目录文件过多 - 淘汰策略:优先删
access_time 且 <code>ref_count == 0的文件;对高热度流(如最近 5 分钟 QPS > 1000),延长 TTL 到 300s
最易被忽略的是:HTTP Cache-Control: max-age=300 和本地磁盘 TTL 必须对齐,否则出现“上游说能缓 5 分钟,本地 2 分钟就删了”的错配。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











