服务器重写阶段

定位阶段

定位重写阶段(可以将请求恢复到上一阶段)

访问控制阶段

try_files 阶段

日志记录阶段

为了生成响应请求所需的内容,nginx将请求传递给适当的内容处理程序。根据确切的位置配置,nginx可能首先尝试所谓的无条件处理程序,如perl、proxy_pass、flv、mp4等。如果请求不匹配上面的任何内容处理程序,则由以下处理程序中的一个按如下顺序选择:random index、index、autoindex、gzip_static、static。

索引模块的详细信息可以在nginx文档中找到,但是这些模块处理以斜杠结尾的请求。如果像mp4或autoindex这样的专门模块不合适,则认为内容只是磁盘上的文件或目录(即静态的),由 static 内容处理程序提供服务。对于一个目录,它会自动重写URI,使末尾斜杠始终存在(然后发出HTTP重定向)。

然后内容处理程序的内容被传递给过滤器。过滤器也附加到位置,并且可以为一个位置配置多个过滤器。过滤器的任务是操作处理程序生成的输出。过滤器的执行顺序在编译时确定。对于开箱即用过滤器,它是预定义的,对于第三方过滤器,它可以在构建阶段进行配置。在现有的nginx实现中,过滤器只能进行出站更改,目前还没有编写和附加过滤器来进行输入内容转换的机制。输入过滤将出现在nginx的未来版本中。

过滤器遵循特定的设计模式。过滤器被调用后,开始工作,并调用下一个过滤器,直到调用链中的最后一个过滤器。然后,nginx完成响应。过滤器不必等待上一个过滤器完成。链中的下一个过滤器可以在上一个过滤器的输入可用时立即开始自己的工作(在功能上非常类似于Unix管道)。反过来,在接收到来自上游服务器的整个响应之前,就可以将生成的输出响应传递给客户端。

有头过滤器和体过滤器;nginx分别将响应头和响应体提供给关联的过滤器。

头过滤器包括三个基本步骤:

nginx配置_nginx php 配置_nginx负载均衡配置

决定是否对此响应进行操作。

操作响应。

调用下一个过滤器.

体过滤器转换生成的内容。体过滤器的例子包括:

在过滤器链之后,响应被传递给写入器。除了写入器之外,还有两个额外的特殊用途过滤器,即 copy 过滤器和 postpone 过滤器。copy 过滤器负责用可能存储在代理临时目录中的相关响应内容填充内存缓冲区。postpone 过滤器用于子请求。

子请求是请求/响应处理的一种非常重要的机制。子请求也是nginx最强大的方面之一。通过子请求,nginx可以从与客户端最初请求的URL不同的URL返回结果。一些web框架称之为内部重定向。然而,nginx更进一步——过滤器不仅可以执行多个子请求并将输出组合成单个响应,而且子请求也可以嵌套和分层。子请求可以执行自己的子请求,孙请求也可以发起它的子请求。子请求可以映射到硬盘、其他处理程序或上游服务器上的文件。子请求对于在原始响应的数据插入额外内容最有用。例如,SSI(服务器端包含)模块使用过滤器解析返回文档的内容nginx配置,然后用指定URL的内容替换 include 指令。或者,它可以是一个过滤器的示例,该过滤器将文档的整个内容视为要检索的URL,然后将新文档追加到URL上。

nginx配置_nginx php 配置_nginx负载均衡配置

upstream 和负载均衡器也值得简要描述。上游用于实现可以定义为反向代理的内容处理程序(proxy_pass处理程序)。upstream 模块主要准备发送到上游服务器(或“后端”)的请求,并从上游服务器接收响应。这里没有对输出过滤器的调用。

upstream 模块所做的事情是设置回调等待上游服务器准备好写入和读取时调用。存在实现以下功能的回调:

负载均衡模块附加到proxy_pass处理程器,当有多个上游服务器符合条件时,提供选择上游服务器的能力。负载均衡器注册一个启用的配置文件指令,提供额外的上游初始化函数(解析DNS中的上游服务器名称,等等),初始化连接结构,决定请求的路由,并更新统计信息。目前nginx支持两种标准的规则来平衡上游服务器的负载:轮询和ip-hash。

upstream 和负载均衡处理机制包括检测失效的上游服务器和将新请求重新路由到其他服务器的算法——尽管计划进行大量额外工作来增强此功能。一般来说,计划对负载均衡器进行更多的开发,在nginx的下一个版本中nginx配置,用于在不同上游服务器之间分配负载以及健康检查的机制将得到极大的改进。

还有一些其他有趣的模块,它们提供了一组额外的变量供配置文件中使用。虽然nginx中的变量是跨不同模块创建和更新的,但是有两个模块完全专用于变量:geo 和 map。geo模块用于根据客户端的 IP 地址进行跟踪。这个模块可以创建依赖于客户端 IP 地址的任意变量。另一个模块 map 允许从其他变量创建变量,本质上提供了灵活映射主机名和其他运行时变量的能力。这种模块可以称为变量处理程序。

进程nginx中单个worker中实现的内存分配机制在某种程度上受到Apache的启发。nginx内存管理的高级描述如下:对于每个连接,必要的内存缓冲区是动态分配,关联,用来存储和操作请求和响应的头和体的,然后在连接释放时释放。值得注意的是,nginx尽量避免在内存中复制数据,并且大多数数据是通过指针值传递的,而不是通过调用memcpy。

nginx负载均衡配置_nginx php 配置_nginx配置

再深入一点,当模块生成响应时,检索到的内容被放入内存缓冲区,然后将内存缓冲区添加到缓冲区链路中。后续处理也适用于这个缓冲链。在nginx中,缓冲链非常复杂,因为根据模块类型的不同,有几种不同的处理场景。例如,在实现体过滤模块时,精确地管理缓冲区可能非常棘手。这样的模块一次只能操作一个缓冲区(链路),它必须决定是覆盖输入缓冲区、用新分配的缓冲区替换缓冲区,还是在相关缓冲区之前或之后插入新的缓冲区。更复杂的是,有时一个模块会接收多个缓冲区,因此它必须对一个不完整的缓冲区链进行操作。然而,此时nginx只提供了一个用于操作缓冲链的低级API,因此在进行任何实际实现之前,第三方模块开发人员应该非常熟悉nginx的这个神秘部分。

关于上述方法的一个注意事项是,存在为连接的整个生命周期分配的内存缓冲区,因此对于长生命周期的连接,会保留一些额外的内存。同时,在空闲的keepalive连接上,nginx只花费550字节的内存。nginx未来版本的一个可能的优化是对长生命周期的连接重用和共享内存缓冲区。

管理内存分配的任务由nginx池分配器完成。共享内存区域用于接受互斥锁、缓存元数据、SSL会话缓存以及与带宽策略和管理(限制)相关的信息。nginx中实现了一个slab分配器来管理共享内存分配。为了同时安全使用共享内存,可以使用许多锁定机制(互斥锁和信号量)。为了组织复杂的数据结构,nginx还提供了一个红黑树实现。红黑树用于将缓存元数据保存在共享内存中,跟踪非非正则表达式位置定义和其他一些任务。

不幸的是,上述所有内容从未以一致和简单的方式进行描述,这使得为nginx开发第三方扩展的工作变得非常复杂。尽管存在一些关于nginx内部构件的优秀文档(例如由Evan miller贡献的那些文档),但是这类文档需要大量的逆向工程工作,并且nginx模块的实现对许多人来说仍然是一门神秘的艺术。

尽管第三方模块开发存在一定的困难,但nginx用户社区最近看到了许多有用的第三方模块。例如,有一个用于nginx的嵌入式Lua解释器模块、用于负载平衡的额外模块、完整的WebDAV支持、高级缓存控制和其他有趣的第三方工作,本章的作者鼓励并将在将来支持这些工作。

14.5. 经验总结

当Igor Sysoev开始编写nginx时,大多数支持Internet的软件都已经存在,而此类软件的体系结构通常遵循遗留服务器和网络硬件、操作系统和旧Internet体系结构的定义。然而,这并没有阻止Igor认为他可以改进web服务器领域的东西。因此,第一个经验显而易见,它是:总有改进的空间。

怀着开发更好的web软件的想法,Igor花了大量时间开发初始代码结构,并研究了针对各种操作系统优化代码的不同方法。十年后,考虑到在版本1上多年的积极开发,他正在开发nginx 2.0版本的原型。很明显,新体系结构的初始原型和初始代码结构对软件产品的未来至关重要。

另一点值得一提的是,开发应该专注。nginx的Windows版本可能是一个很好的例子,说明了避免开发人员的核心能力或目标应用程序之外的工作耗费太多精力是值得的。它同样适用于重写引擎,出现多次尝试使用更多特性增强nginx,以便与现有遗留设置向后兼容。

最后但同样重要的,值得一提的是,尽管nginx开发人员社区不是很大,但第三方模块和扩展一直是nginx广受欢迎的重要原因。Evan Miller、Piotr Sikora、Valery Kholodkov、Zhang Yichun (agentzh)等优秀软件工程师的工作得到了nginx用户社区及其原始开发人员的高度赞赏。

(全文完)

点击下方

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688