百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

没有 NGINX 和 OpenResty 的未来

off999 2025-02-08 12:24 28 浏览 0 评论

没有 NGINX 和 OpenResty 的未来:Cloudflare 工程师正花费大量时间用 Rust 重构现有功能

作者 | Tina、核子可乐

在 Cloudflare 公司,工程师们正在花费大量时间重构或重写现有功能。


当每年处理的流量增长一倍时,原本最优雅的问题解决方案往往会随着工程约束条件的变化而迅速过时。不仅如此,面对每秒高达 4000 万的请求总量,即使流经 Cloudflare 网络的全部请求中有 0.001% 发生问题,代表的也是冲击数百万用户的大事件。或者从另一个角度讲,发生概率仅为万亿分之一的罕见事件在这样的运行规模下每天都会出现。这就是 Cloudflare 所面临的最大的问题。


长期以来,Cloudflare 一直依赖 Nginx 作为其 HTTP 代理堆栈的一部分。随着 Cloudflare 规模的扩大, NGINX 的处理能力已经不能满足业务需求了。


去年 9 月,他们宣布已将 Nginx 替换为其内部由 Rust 编写的 Pingora 软件,想以此建立一个更快、更高效、更通用的内部代理,作为他们当前和未来产品的平台。


但这还不是全部,上周 Cloudflare 又发布了一篇博客称,他们用 Rust 编写了 Cloudflare 基础设施中最古老和最不为人所知的部分 cf-html 的替代品。Cf-html 是一套用于在网站源到网站访问者之间解析并重写 HTML 的框架。从创立之初起,Cloudflare 就提供相关功能,可以为用户即时重写 Web 请求的响应正文。它位于 Cloudflare 核心反向 Web 代理 FL(Front Line)之内。FL 运行着 Cloudflare 应用程序的大部分逻辑,因此无疑这次替换更具有挑战性。


同时 FL 作为 OpenResty 的一部分运行在 NGINX 之上,“通过这样做,我们为完全摆脱 NGINX 铺平了道路。”“很明显,这套曾经代表着开发者易用性与速度性最佳组合的平台,已经开始显露出明确的时代局限性。”


“我们正在逐步替换掉用于运行 NGINX/OpenResty 代理的组件”,从而构建一个“没有 NGINX 的未来”。



“内存安全”也是一大原因


FL 主要由 Lua 脚本语言编写的代码组成,作为 OpenResty 的一部分运行在 NGINX 之上。为了直接与 NGINX 进行交互,其中某些部分(如 cf-html)是用 C 和 C++ 等低级语言编写的。


过去,Cloudflare 掌握着大量这样的 OpenResty 服务,但现在留下的就只有 FL 等为数不多的几种了,其他组件已经被转移到了 Workers 或者基于 Rust 的代理处


所有 cf-html 逻辑都是用 C 语言编写的,因此跟其他大型 C 代码库一样,它也容易受到内存损坏问题的困扰。2017 年,团队在尝试替换部分 cf-html 时就曾引发安全漏洞。FL 从内存中读取任意数据并将其附加至响应主体,而这可能包含同一时间通过 FL 的其他请求中的数据。这次安全事件,也就是后来广为人知的 Cloudbleed


自那次事件以来,Cloudflare 实施了式项政策和保障措施,以确保不再发生类似的问题。虽然多年来一直在 cf-html 上开展工作,但该框架几乎没有实现什么新功能。现在的业务情况导致大家对 FL 中的任何崩溃都非常敏感(当然,对网络上任何进程的崩溃都很敏感),特别是那些可能影响到响应性能的问题。


时间快进到 2022、2023 年,FL Platform 团队收到的请求越来越多,大家希望改用新的系统,从而轻松查看和重写响应主体数据。与此同时,Cloudflare 的另一支团队一直在为 Workers 开发新的响应主体解析和重写框架,名为 lol-html,即低输出延迟 HTML。Lol-html 不仅比 Laxy HTML 更快、更高效,而且目前已经在 Worker 接口中得到了全面的生产应用。另外,它是用 Rust 编写的,所以在内存处理方面比 C 语言安全得多。


“总而言之,Lol-html 正是我们用来替换 FL 中古老陈旧 HTML 解析器的理想选项。”Cloudflare 的工程师 Sam Howson 在博客中表示。



于是乎,该团队开始尝试用 Rust 编写新的框架,让该框架把 lol-html 合并进来。这样既能帮助其他团队编写响应主体解析功能,又不会造成大量安全问题。新系统被定名为 ROFL,即 FL 响应监工(Response Overseer for FL),这是一个完全用 Rust 编写的全新 NGINX 模块。


截至目前,ROFL 已经在生产环境中每秒处理数百万个响应,其性能可以与 cf-html 相媲美。“在构建 ROFL 的过程中,我们得以弃用 Cloudflare 整个代码库中最糟糕的部分,同时给 Cloudflare 各团队提供了一套强大系统,供他们以响应主体数据解析和重写为基础编写出更多功能。”


个中挑战


给飞机更换引擎总会有一些挑战。


NGINX 模块系统也给各模块的工作方式提供了极大的灵活性,使其能高度匹配特定用例。当然,这种灵活性设计也有相应的问题。他们遇到的一大挑战,跟 Rust 和 FL 之间的响应数据处理方式有关。在 NGINX 当中,响应主体会被拆分成块,之后将这些块串连起来形成一个列表。另外,如果响应规模很大,则每条响应可能对应多个链接列表。


要想高效处理这些块,就需要加快对各个块的处理和传递速度。在编写用于操作响应的 Rust 模块时,大家往往会想到在链表中采用基于 Rust 的视图。但如果这样做,就必须确保在变更基于 Rust 的视图时,也一并更新底层 NGINX 数据结构,否则 Rust 与 NGINX 间的不同步会导致严重 bug。Cloudflare 工程师以 ROFL 早期版本中的一条令人头痛的小函数为例,讲解了他们曾经遇到过的挑战。


fn handle_chunk(&mut self, chunk: &[u8]) {
    let mut free_chain = self.chains.free.borrow_mut();
    let mut out_chain = self.chains.out.borrow_mut();
    let mut data = chunk;


    self.metrics.borrow_mut().bytes_out += data.len() as u64;


    while !data.is_empty() {
        let free_link = self
            .pool
            .get_free_chain_link(free_chain.head, self.tag, &mut self.metrics.borrow_mut())
            .expect("Could not get a free chain link.");


        let mut link_buf = unsafe { TemporaryBuffer::from_ngx_buf(&mut *(*free_link).buf) };
        data = link_buf.write_data(data).unwrap_or(b"");
        out_chain.append(free_link);
    }
}

这段代码的设计目标是获取 lol-html 的 HTMLRewriter 输出,并将其写入缓冲区的输出链。重要的是,输出可能大于单一缓冲区,所以需要在循环内从链中取出新的缓冲区,直到将所有输出均写入缓冲区。在这样的逻辑中,NGINX 应该负责从空闲链中取出缓冲区,再将新块附加到输出链上。它确实也是这么做的,但如果只考虑 NGINX 处理链表视图的方式,往往会忽视 Rust 不会更改其 free_chain.head 所指向的缓冲区。


这就导致逻辑永远循环,且 NGINX 工作进程完全锁定。这类问题可能需要很长时间才能发现,特别是在意识到其根源与响应主体的大小有关之前,他们甚至没法稳定地加以重现。


另外,使用 gdb 获取 coredump 来执行分析也很困难,因为当大家注意到内存占用过量而开始写入硬盘时,进程内存已经增长到了可能令服务器崩溃的程度,这时候做什么都太晚了。幸运的是,这段代码从没被投入生产环境。跟以往一样,虽然 Rust 编译器能帮助团队发现很多常见错误,但如果数据是通过 FFI 共享自另一个环境,那么即使不直接使用 unsafe 也会存在很多隐患。所以必须格外小心,特别是在 NGINX 的这种灵活性“优势”可能导致整台设备停止服务的情况下。


该团队面临的另一个重大挑战,跟传入响应正文块的背压有关。本质上,如果 ROFL 因必须向传输流中注入大量代码(例如用大量 JavaScript 替换电子邮件地址)而增加了响应的大小,则 NGINX 能以比单独推出更快的速度,将 ROFL 的输出提供给其他下游模块。这时如果下一模块的 EAGAIN 错误未得到处理,则可能导致数据被丢弃、HTTP 响应主体被截断。这也是个很难通过测试发现的问题,因为大多数时候响应的刷新速度是够的,背压并不会造成影响。为了将其解决,他们创建了一条特殊的链来存储这些被称为 saved-in 的块,再用一种特殊的方法完成附加。


#[derive(Debug)]
pub struct Chains {
    /// This saves buffers from the `in` chain that were not processed for any reason (most likely
    /// backpressure for the next nginx module).
    saved_in: RefCell,
    pub free: RefCell,
    pub busy: RefCell,
    pub out: RefCell,
    [...]
}


实际上,Cloudflare 工程师们决定在短时间内对数据进行“排队”,这样就不会因为提供速度超出处理速度而冲垮其他模块。NGINX 开发者指南中提供了很多重要的信息,但这里的案例显得比较孤立、不成体系,所以并没有包含他们遇到的问题。这类情况其实是 NGINX 复杂工作环境所催生出的结果,往往只有少数用户能够发现。


写在最后


Cloudflare 工程师对 Rust 表现出了极度的热爱,并在整个基础设施中使用它来获得内存安全优势、更现代的功能和其他优势。


该博客还指出,他们正在招聘更多的 Rust 工程师,并谈到了 Rust 对他们的好处:


“这里我们要特别感谢 Rust 的存在,只有这款语言能让我们在获得速度优势的同时实现高安全性,并获得 Bindgen 和 Serde 等高质量库的协助。


大多数人认为编程语言的安全性优势只体现在预防 bug 上,但事实不仅如此——作为一家规模化企业,我们发现语言的安全优势还能让某些极度困难、甚至原本认为与安全相悖的目标成为现实。


无论是用类似 Wireshark 的过滤语言来编写防火墙规则、允许数百万用户编写任意 JavaScript 代码并直接在我们平台上运行,还是即时重写 HTML 响应,Rust 都为我们的服务划定了严格的执行边界,让这种种不可能成为了可能。我们也欣慰地看到,Rust 的普及正逐步将那些曾经困扰开发行业的内存安全问题丢进历史的垃圾堆。”


声明:本文为 InfoQ 翻译整理,未经许可禁止转载。


本文转载来源:

https://www.infoq.cn/article/w7cv5XqAMa4RpOm1ollT

相关推荐

苹果笔记本电脑2025年新款(苹果笔记本电脑2025年新款价格)

2021年苹果即将上市新款的笔记本电脑,这款新的笔记本电脑,他的设计是非常好的非常流行,非常高端,大气笔记本电脑的质量是比较轻的它采用的材质也是非常高端的材质非常结实的质量,很轻,电脑的内存要变202...

迅雷电影下载网站(迅雷电影下载网站1080P下载)

目前,有很多好的迅雷下载电影的网站供选择。其中,BT天堂、猫扑电影网、人人影视等都是不错的选择。这些网站拥有庞大的资源库,提供各类电影资源的下载。此外,它们的界面简洁明了,操作方便快捷,用户体验较好。...

国内哪个应用商店app最全(国内软件商店)

1.MicrosoftToDo推荐理由:微软出品,必属精品2.Microsoft便笺推荐理由:又是一款微软官方出品的良心免费应用,相比MicrosoftToDo,Microsoft便笺更加...

不知道路由器密码怎么办(不知道路由器的密码怎么连接)

通过其他设备找回如果遇到wifi密码忘记的情况,我们可以通过其他设备来找回,例如你家中的笔记本电脑是否可以正常连接wifi吗,如果你的笔记本还处于连接wifi状态,那么可以点击笔记本电脑右下角的网络图...

bios正确设置(bios正确设置方法)

方法/步骤1/8目前市面上较流行的主板BIOS主要有AwardBIOS、AMIBIOS、PhoenixBIOS三种类型,由于phoenix公司与AMI公司合并了,所以现在常用的只有award和...

安全模式进不去蓝屏(安全模式进不去一直蓝屏)

如果在Windows10中遇到蓝屏问题,并且无法进入安全模式,可以尝试以下方法:1.使用高级启动选项:重启计算机,并在启动过程中按住Shift键,直到出现高级启动选项。从列表中选择"故障排...

win732位系统多大(win732位系统支持多大硬盘)

您好,32位Windows7的所有版本均支持4GB内存,但32位的Windows7实际可利用的最大内存只有3.25GB左右。64位的Windows7家庭普通版能支持8GB内存,家庭高级版能支持1...

win10修改电脑开机密码(win10修改电脑开机密码在哪里)

win10系统这样重设开机密码:具体的步骤如下:1、点击Win10的“开始”按钮,继续点击“设置”选项。2、点击“账户”选项。3、点击左侧的“登录选项”,接着在“密码”选项下点击“更改”。4、首先会弹...

办公软件office下载(office办公软件正版下载)

office字体都变成了英文是因为设置了英文模式。具体的解决步骤如下:我们需要准备的材料分别是:电脑、Word文档。1、首先我们打开Word文档,点击打开左上角的文件中的“选项”。2、然后我们在弹出来...

windows打开注册表(windows打开注册表编辑器的命令)

如果装了杀毒软件,并且开了注册表保护功能,关闭此功能,如果关闭后可以正常写入了,说明是这个问题造成的,之所以打开后不能写入了,是由于注册表保护功能的提示项目被关闭了,打开设置项目,打开提示即可,这样以...

win7本地组策略编辑器怎么打开

1、在桌面上新建一个记事本文件,随后双击打开它将下方的代码全部复制粘贴进去:  @echooff  pushd"%~dp0"  dir/bC:\Windows\servicing\Packag...

笔记本连接不上无线网(笔记本连接不上无线网络)

1、笔记本电脑连不上wifi原因有很多,如果是所有WIFI都连接不上,那就是电脑自身设置出错。2、方法一:电脑连不上wifi,图标会有黄色叹号,在右下角右键点击无线wifi图标,再点击打开网络和共享中...

国内杀毒软件(国内杀毒软件有哪些完整名单)

小米手机自带的安全中心中就有病毒扫描功能,可能小米与360不太兼容,不过我觉得小米自带的杀毒也可以的,不用再单独下载一个杀毒软件了,我觉得是软件问题,因为有的软件手机是不支持的,强行安装后就会出现启动...

tplink18r18e如何设置(tplink19216811路由器设置)

TL-H28R路由器恢复了出厂设置,现在要设置其连接宽带上网,需要经过以下几个步骤:1、TL-H28R路由器与TL-H28E扩展器注册;将TL-H28R路由器和TL-H28E扩展器分别插到电源插座上,...

win7现在还能用吗(win7现在还能用么2021年)
win7现在还能用吗(win7现在还能用么2021年)

WINDOWS7系统还可以用多久?什么时候会被淘汰?先不说WINDOWS7系统可以用多久,先说说XP系统到目前为止可以在系统之家上搜索,并且下载,只要硬件支持,XP系统都可以继续在使用,也不用担心,XP系统在使用的过程中系统出现崩溃或者...

2025-12-03 21:03 off999

取消回复欢迎 发表评论: