How we built Pingora, the proxy that connects Cloudflare to the Internet
基于 Rust 构建 Pingora,作为 Nginx 的替代方案;
Nginx 作为常用代理服务,广泛应用于 CDN、WAF、Stream、Tunnel 等场景,是基础网络设施
然而,Nginx 在作为客户端-服务端代理时,存在以下不足:
- master-worker 进程架构导致的连接池不复用
Nginx 是多进程架构,master进程作为管理进程处理reload等命令;其管理的多个worker进程进行实际的网络处理,完成代理任务。处理客户端连接时,由master进程接受后分发给每个woker,客户端连接是共享的。但是,多个worker之间不能共享与后端的TCP连接,每个worker进程有自己的连接池。
当多个客户访问同一个后端服务,请求到每个worker进程后分别与后端建立连接,这导致Nginx有较多的资源和内存浪费。
如果能够让多个worker进程复用连接池,将能很好地节省资源。
- 实现复杂功能的困难
Nginx 能够很好地做到 web 服务器,负载均衡,代理服务等工作,但是实际应用时往往需要实现更多的逻辑和功能。比如,作为代理服务时,如果想实现一个功能:当后端响应失败时,请求其它备用服务后端,再进行返回。就会比较难,这并不在 Nginx 架构的定义之内,实现很复杂。
因此,对 Nginx 的架构做出调整,有利于此类基础设施的更广泛的应用。
- 内存安全与静态类型的困难
Nginx 是基于 C 语言实现的,而 C 语言是内存不安全的,增加模块或改进时都很容易出现内存溢出问题,这是一个网络基础设施程序不应该存在的问题。
尽管有 Openresty 的实现,能够通过 lua 代码对 nginx 进行扩展。lua 尽管是内存安全的脚本,但是其是动态语言,当使用 lua 实现复杂的功能、定义复杂的数据对象时,代码维护难度很大。
因此,解决 C 语言内存安全的问题,并且能会用类型安全、静态的语言实现扩展模块,将会增强此类基础设施的能力。
因此,基于 Rust 语言实现的 Pingora 成为了解决方案。Pingora 具有以下特性:
- 多线程架构替代多进程架构
Pingora 采用多线程架构实现,使得连接池可以被共享,减少了与后端服务的连接。
替换了Nginx的master-worker多进程架构,节省了网络资源。
- 实现类似Openresty的请求生命周期管理
为了方便对Pingora进行扩展,将基础组件和扩展功能进行了分离,并且实现了生命周期划分和扩展实现。这使得原先的Nginx开发者能够平稳过渡到Pingora,且能实现更多功能的扩展。
- 基于Rust实现内存安全
基于Rust实现,解决了 C 语言的内存问题。
- 更多的特性
基于HTTP/2 upstream,增加了支持到Pingora中,可以实现grpc的代理。
使用 R2 storage 作为缓存代理,实现高效的内容缓存服务。
Open sourcing Pingora: our Rust framework for building programmable network services
基于Pingora的功能,可以帮助有以下需求的应用开发:
- 内存安全需求,设施运行稳定性要求高
- 性能敏感需求,需要低运行消耗,减少内存资源消耗
- 客户定制化需求,在代理服务器之上,需要实现定制化的功能
Pingora的特性:
- 多种协议的代理:As a proxy, it supports HTTP/1 and HTTP/2 end-to-end, gRPC, and websocket proxying. (HTTP/3 support is on the roadmap.)
- 满足定制化开发需求:Pingora provides filters and callbacks to allow its users to fully customize how the service should process, transform and forward the requests
- 运维管理方便:Pingora provides zero downtime graceful restarts to upgrade itself without dropping a single incoming request
- 运维监控方便:Syslog, Prometheus, Sentry, OpenTelemetry and other must-have observability tools are also easily integrated with Pingora as well
总结
Pingora 实现了很多网络基础库,实现了原先 Nginx 的功能。但是,其目前主要是提供了代码库实现,还没有做到 Nginx 可以用 conf 配置文件实现复杂功能的能力。即当前只是支持使用 Pingora 库,自己再写代码实现所需的功能,还无法像用 Nginx 那样直接配置conf就可以实现很多需求。
总的来说,Nginx 已经是一个成熟的软件(其可扩展)。但是 Pingora 是一组基础代码库的集合,基于这些基础库可以实现原先Nginx 可以实现的功能,而不是"配置出"原先Nginx可以实现的功能。