Pingora 的开源——Cloudflare 基于 Rust 搭建的用于替换Nginx的网络框架

2024 年 2 月,Cloudflare 宣布将 Pingora 以 Apache 2.0 协议开源。

Pingora 不是一个新项目。在此之前,它已经在 Cloudflare 的全球网络上悄悄运行了相当长时间,处理了将近一千万亿次互联网请求。Cloudflare 用它替换了 NGINX,它是 CDN、WAF、Workers 等核心产品背后的代理引擎。

这次开源,是 Cloudflare 第一次把这个内部核心框架完整地交给社区。

原文链接:https://blog.cloudflare.com/pingora-open-source/
开源仓库:https://github.com/cloudflare/pingora
文档:https://github.com/cloudflare/pingora/tree/main/docs


为什么在这个时间节点开源

在技术层面,Pingora 的定位很清楚------一个用 Rust 编写的异步多线程 HTTP 代理框架。但开源的动机,不只是"分享一个好用的库"这么简单。

2024 年初前后,内存安全的话题在行业里密度明显上升。美国白宫发布技术报告,明确点名内存不安全语言带来的系统性安全风险,呼吁向内存安全语言迁移。微软、谷歌等公司陆续公开内部数据,表明大量安全漏洞的根源是 C/C++ 代码里的内存管理错误。

在这个背景下,Cloudflare 开源 Pingora 的意图超出了一次普通的技术分享:他们希望为那些仍在用 C/C++ 构建网络基础设施的团队,提供一条可验证的迁移路径。

为了推动这件事落地,Cloudflare 还专门与 ISRG(互联网安全研究组,也就是 Let's Encrypt 的母组织) 下的 Prossimo 项目展开合作,目标是把 Pingora 推向互联网最关键的基础设施层。


Pingora 到底能做什么

Pingora 的定位是一个框架,而不是一个开箱即用的产品。它提供的是构建网络服务所需的底层积木,使用者在上面实现自己的业务逻辑。

协议支持方面,Pingora 覆盖了主流场景:

  • HTTP/1 和 HTTP/2 的端到端代理
  • gRPC 和 WebSocket 代理
  • TLS、TCP 和 Unix Domain Socket
  • HTTP/3 列在路线图上,尚未发布

负载均衡方面,框架内置了轮询、哈希等常用策略,也支持完全自定义的服务器选择逻辑。

安全方面,同时支持 OpenSSL 和 BoringSSL,BoringSSL 的版本支持 FIPS 合规和后量子密钥协商。

运维方面,支持零停机优雅重启------升级服务时不丢弃任何进行中的连接。可观测性方面,Syslog、Prometheus、Sentry、OpenTelemetry 等工具都可以直接集成。


什么样的团队适合用 Pingora

Cloudflare 在博客里列了三类场景,值得对号入座:

安全优先的场景:如果你的服务目前是 C/C++ 写的,且面临过内存安全相关的漏洞或审计压力,Pingora 是一个经过生产验证的替代方案。Cloudflare 自己的经验是:迁移到 Rust 之后,内存类 bug 在代码评审和上线后几乎不再出现,这让工程师有更多精力做功能迭代。

性能敏感的场景:相比 NGINX 的多进程模型,Pingora 的多线程架构让所有线程共享同一个连接池,连接复用率显著更高。Cloudflare 内部数据显示迁移后 CPU 节省约 70%,内存节省约 67%。

需要深度定制的场景 :Pingora 提供了一套类似 OpenResty *_by_lua 风格的回调体系,可以在请求处理的不同阶段注入自定义逻辑------修改请求头、重写路由、自定义认证、记录日志。如果你需要构建一个高度定制的网关或负载均衡器,Pingora 的 API 设计方向和你的需求天然匹配。


动手:50 行 Rust 写一个负载均衡器

博客里给出了一个完整的示例,展示 Pingora 的编程模型。以下把这个例子拆开讲清楚。

第一步:定义代理结构体

Pingora 里,任何实现了 ProxyHttp trait 的结构体,就是一个 HTTP 代理。这个 trait 唯一必须实现的方法是 upstream_peer(),每个请求进来都会调用它,返回值决定请求被转发到哪台服务器:

rust 复制代码
pub struct LB(Arc<LoadBalancer<RoundRobin>>);

#[async_trait]
impl ProxyHttp for LB {
    async fn upstream_peer(
        &self,
        _session: &mut Session,
        _ctx: &mut Self::CTX,
    ) -> Result<Box<HttpPeer>> {
        let upstream = self.0
            .select(b"", 256)  // 轮询模式下哈希值无关紧要
            .unwrap();

        // 设置 SNI,指向目标域名
        let peer = Box::new(HttpPeer::new(
            upstream,
            true,
            "one.one.one.one".to_string()
        ));
        Ok(peer)
    }
}

这里的 LoadBalancer<RoundRobin> 是框架内置的,直接用就行。如果需要更复杂的选择逻辑------比如根据请求参数做哈希,或者接入服务发现------在这个函数里自己实现即可。

第二步:启动服务

把服务器 IP 硬编码进去,绑定一个本地端口,服务就起来了:

rust 复制代码
fn main() {
    let upstreams =
        LoadBalancer::try_from_iter(["1.1.1.1:443", "1.0.0.1:443"]).unwrap();

    let mut lb = pingora_proxy::http_proxy_service(
        &my_server.configuration,
        LB(Arc::new(upstreams))
    );
    lb.add_tcp("127.0.0.1:6188");

    let mut my_server = Server::new(None).unwrap();
    my_server.add_service(lb);
    my_server.run_forever();
}

实际工程里,上游服务器列表可以来自服务发现系统,在 upstream_peer() 被调用时动态查询,或者在后台线程里定期刷新。

第三步:用过滤器修改请求头

把上面的代码跑起来,用 curl 测试会发现服务器返回 403。原因是代理直接把客户端发来的 Host: 127.0.0.1:6188 转发给了上游,上游不认识这个 Host,直接拒绝了。

修复方式是加一个 upstream_request_filter,在请求发出去之前把 Host 头改掉:

rust 复制代码
async fn upstream_request_filter(
    &self,
    _session: &mut Session,
    upstream_request: &mut RequestHeader,
    _ctx: &mut Self::CTX,
) -> Result<()> {
    upstream_request
        .insert_header("Host", "one.one.one.one")
        .unwrap();
    Ok(())
}

加上这个过滤器之后,请求正常返回 200。

这个例子展示的是 Pingora 编程模型的核心思路:框架处理连接池、TLS 握手、读写缓冲、协议解析这些通用逻辑,你只需要实现关心的那几个回调。目前 Pingora 提供了覆盖请求生命周期各阶段的过滤器,包括请求到达、上游连接建立、请求转发、响应接收、响应转发等。


需要了解的现实局限

Pingora 是一个引擎,而不是一辆完整的车------这是博客里 Cloudflare 自己打的比方。

它目前是一个库和工具集,不是一个像 Nginx 那样配置几行就能跑起来的独立程序。如果你的目标是零代码配置一个反向代理,Pingora 不是正确的起点。Cloudflare 正在和 ISRG 合作,在 Pingora 之上构建一个更完整、更开箱即用的产品,但那是另一个项目。

另外两个重要的注意事项:

API 稳定性:Pingora 目前处于 1.0 之前的阶段,API 随时可能变动,过滤器的签名和行为都可能在后续版本里调整。如果要在生产环境引入,需要做好适配升级的心理准备。

操作系统支持:目前只支持 Unix 系的系统(Linux、macOS)。Windows 暂时不在路线图上。


开源之后

在规模上,Pingora 是少数几个经过真正大规模验证的 Rust 网络框架之一。它不是实验性的,而是在 Cloudflare 每天承载数百亿次请求的生产环境里跑了多年。

对于正在考虑以下任何一件事的团队,它值得认真评估:

  • 把现有的 C/C++ 代理服务迁移到内存安全的实现
  • 构建一个需要深度定制的 API 网关或流量控制层
  • 在高性能要求下用 Rust 构建网络服务

它也是目前 Rust 网络服务生态里,罕见的同时满足"经过大规模生产验证"和"提供完整可编程 API"两个条件的框架。

相关推荐
Koma_zhe2 小时前
【Ansible开源自动化运维工具】别再手动装监控了,Ansible能让上百台机器同时搞定Node Exporter(1)
运维·开源·ansible
darkb1rd3 小时前
deepclaude:低成本指南,17 倍省调用费
开源·github·好物分享
DogDaoDao4 小时前
【GitHub】System Informer:Windows 平台最强开源系统监控与调试利器
windows·程序员·开源·github·开发工具·system informer
tsyjjOvO4 小时前
Nginx 从入门到实践:反向代理、负载均衡与动静分离
nginx·负载均衡
StackNoOverflow4 小时前
Nginx 入门教程(安装、反向代理、负载均衡、动静分离)
运维·nginx·负载均衡
鬼蛟5 小时前
Nginx
运维·nginx
余识-5 小时前
古竹:将时间化作最有价值的投资
金融·rust·业界资讯·tauri·投资·基金