Nginx
2010-09-13 09:33:35 阿炯

Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。Nginx 是由 伊戈尔·西索夫(Igor Sysoev) 为俄罗斯当时访问量第二的Rambler站点开发的,它已经在该站点运行超过多年了。Igor 将源代码以类BSD许可证的形式发布,自Nginx发布以来,已经因为它的稳定性、丰富的功能集、简明的示例配置文件和低系统资源的消耗而闻名了。目前大型网站已经部署了Nginx。

nginx [engine x] is an HTTP and reverse proxy server, as well as a mail proxy server, written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VKontakte, and Rambler.

体系架构

1. Master 进程
处理信号
通知并监视 Worker 进程
启动 Worker 进程

2. Worker 进程
接收和响应信号处理;处理客户端请求;


3. Cache loader 进程
加载缓存文件索引。

4. Cache manager 进程
管理磁盘缓存大小;超出阈值通过最少使用原则进行删除。



nginx生态圈的重要开源模块和产品

Nginx是纯C实现的软件,源码质量很高,即使不从事nginx的人也可以将它作为很好的学习软件。作者Igor很早就有支持脚本语言的意图,所以问题就变成了C如何跟脚本语言引擎的结合了。这些主流脚本语言python、php、v8(js)、perl、lua都有C的API,考虑到两方面:轻量级和性能,perl成为了当时的nginx首选。甚至他还实现了一个迷你的SSI模块,自定义的脚本功能。但是从现在看,觉得Lua才是和C交互最好的语言,天生为C设计的脚本语言,足够轻量,足够快。章亦春(agentzh)将Lua引入nginx,怎么看都是正确和极具工程实用的选择;估计nginx社区也没料到Lua模块能如此成功。

但是Igor一直有脚本语言的情节,于是在2015年NJS诞生了,也是纯C的JS引擎。Lua天生能跟C交互,但不意味着它能天生跟服务器软件交互。这里最大的问题是语言虚拟机的实现。简单讲,一个请求会有个vm,非常轻量级,不用担心。对nginx的每个请求,Lua的vm虽然做了些处理,但还是可以相互影响,如果你想做的话。但是Lua有GC,这也让这问题变的不是很严重。Igor的NJS是专门为nginx量身定制的JS引擎,还考虑到JS有如此大的用户群体。NJS的每个请求的vm都是相互独立的,不会有任何影响,但是它没有GC。早期GC是列入NJS的计划的,但现在已经变的很遥远了,实现成本太大。这个在 HTTP请求也不是问题,nginx对每个请求都是统一分配和销毁的。如果用户想在配置上增强nginx,比如鉴权,NJS是个很好的选择,这也是它的设计初衷。

Nginx的模块化机制从第一个版本就有了,但是当时Igor并不是为了第三方考虑的,只是为了方便自己的开发。用nginx的人大都会为它的模块化机制感到惊叹,谁都可以不用改nginx源码,只需加入自己的模块,以满足自己的需求。Lua就是最好的例子;但这问题也让Igor很恼火,为什么呢?大量的第三方模块,质量参差不齐,它们严重依赖nginx的api。nginx是20年前的软件,当时的服务器架构跟如今已经不可同日而语。软件需要进化,就要做重构,但是api不能轻易改。关注nginx社区的人知道,Igor亲自设计了另一个跟nginx不同的软件单元,这软件不会再支持模块化了,这是他们的选择。所以从短期看,nginx的模块化让它快速建立了整个生态。从长期看,整个生态也束缚在它的架构上。nginx最大的问题不具备热加载,这种现在主流软件里已经不是问题,反而在它这里变成很棘手的问题,好在很多以Lua为主的应用可以解决这个问题。

Nginx的C实现和模块化机制,让Lua的引入变得顺其自然。虽然也有其它的语言已经支持,但如今证明只有Lua玩转的最好,或者说OpenResty做的最成功。严格来说,OpenResty里的Lua不能叫Lua,是LuaJIT,它以Lua5.1语法为主的另一个分支,而且看着没有跟进官方Lua的计划。Lua5.1以后的版本在语法上有了不少的改进,类似位运算,性能更是如此。对单纯使用Lua而言,非常推荐Lua5.4。

OpenResty让很多开发者大幅提升了开发生产力,并且在它上面衍生了不少开源软件,尤其在API方面,比如Kong和APISIX;也很多公司也有内部的自研尝试。不管多么熟悉nginx源码的开发者,还是只是想用它作为应用服务器,脚本语言都是其中的选择之一。从两方面看nginx:通用功能和业务功能。

通用功能:将它扔进nginx里,如果你能做模块开发,这点尤为重要,这意味着你将享受未来稳定和维护的红利。

业务功能:这个不用多说,维护好业务模块就行了。

从整体看,Lua既封装了nginx的HTTP请求,也提供了独立于请求的功能,比如timer(定时器)和cosocket(跟第三方交互的基础机制)。不管什么模块,也都是基于这两方面进行设计的。如果想学习nginx,对程序员,长期保持自己的竞争力,自研能力是很重要的技能之一。用Lua作为开发的,不妨自己写个框架,如今API框架是非常好的练手对象。

根据 nginx 发布新版的策略,“稳定”指的是功能和更新频率,它与软件质量无关。稳定分支在其生命周期中从不接收新功能,并且通常仅接收一个或两个更新,用于修复严重的错误。另外,稳定版本通常 fork 自最新的 mainline 版本。因此,nginx 1.18.0 fork 自最新的 mainline 版本 1.17.10,它继承了过去一年中 1.17.x 的所有 bugfix 补丁、新增功能和其他变更。

Nginx版本更新录(202x)


官方主页:http://nginx.org/

中文维基:http://wiki.nginx.org/NginxChs

该文章最后由 阿炯 于 2025-09-14 11:53:42 更新,目前是第 2 版。