nginx网关概述

前言

“网关” 这东西,感觉离我好远,又感觉很近。“nginx” 是从所周知拥有着高性能的网关。有事我会想“nginx这么高性能,能不能用来做点什么”。

nginx架构

nginx在启动后,在unix系统中会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。
在这里插入图片描述

  • master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。
  • worker进程中来处理基本的网络事件。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
  • 我们也可以手动地关掉后台模式,让nginx在前台运行,并且通过配置让nginx取消master进程,从而可以使nginx以单进程方式运行.显然,生产环境下我们肯定不会这么做,所以关闭后台模式,一般是用来调试用的
  • worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的
在nginx启动后,如果我们要操作nginx,要怎么做呢?
  1. master来管理worker进程,所以我们只需要与master进程通信就行了
  2. master进程会接收来自外界发来的信号,再根据信号做不同的事情
    • 比如master接收到 ./nginx -s reload,就是来重启nginx
    • 首先master进程在接到信号后,会先重新加载配置文件,
    • 然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。
    • 新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出
worker进程又是如何处理请求的呢?
  1. 每个worker进程都是从master进程fork过来,在master进程里面,先建立好需要listen的socket(listenfd)之后,
  2. 然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接
为什么nginx可以采用异步非阻塞的方式来处理呢

异步非阻塞的事件处理机制(select/poll/epoll/kqueue)。它们提供了一种机制,让你可以同时监控多个事件,调用他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。《网络IO模型》。这样,就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。与多线程相比,这种事件处理方式是有很大的优势的

  • 不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。
  • 并发数再多也不会导致无谓的资源浪费(上下文切换)。更多的并发数,只是会占用更多的内存而已。 我之前有对连接数进行过测试,在24G内存的机器上,处理的并发请求数达到过200万。现在的网络服务器基本都采用这种方式,这也是nginx性能高效的主要原因。

我们之前说过,推荐设置worker的个数为cpu的核数,在这里就很容易理解了,更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。而且,nginx为了更好的利用多核特性,提供了cpu亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效

基本的web服务器

对于一个基本的web服务器来说,事件通常有三种类型,网络事件、信号、定时器。从上面的讲解中知道,网络事件通过异步非阻塞可以很好的解决掉。如何处理信号与定时器?

  • 信号的处理。对nginx来说,有一些特定的信号,代表着特定的意义。信号会中断掉程序当前的运行,在改变状态后,继续执行。如果是系统调用,则可能会导致系统调用的失败,需要重入。(关于信号的处理,大家可以学习一些专业书籍,这里不多说)
  • 定时器。由于epoll_wait等函数在调用的时候是可以设置一个超时时间的,所以nginx借助这个超时时间来实现定时器。nginx里面的定时器事件是放在一颗维护定时器的红黑树里面,每次在进入epoll_wait前,先从该红黑树里面拿到所有定时器事件的最小时间,在计算出epoll_wait的超时时间后进入epoll_wait。

nginx的模块化体系结构

了解了nginx进程模型与事件模型之后,我们看看nginx的内部结构。是由核心部分和一系列的功能模块所组成。

  • nginx core实现了底层的通讯协议,为其他模块和nginx进程构建了基本的运行时环境,并且构建了其他各模块的协作基础。(例:web服务反向代理)
  • nginx将各功能模块组织成一条链,当有请求到达的时候,请求依次经过这条链上的部分或者全部模块,进行处理。每个模块实现特定的功能。(例:请求解压缩的模块)
  • 有两个模块比较特殊,他们居于nginx core和各功能模块的中间。这两个模块就是http模块和mail模块

nginx的模块根据其功能基本上可以分为以下几种类型:

模块介绍
event module搭建了独立于操作系统的事件处理机制的框架,及提供了各具体事件的处理。包括ngx_events_module, ngx_event_core_module和ngx_epoll_module等。nginx具体使用何种事件处理模块,这依赖于具体的操作系统和编译选项。
phase handler此类型的模块也被直接称为handler模块。主要负责处理客户端请求并产生待响应内容,比如ngx_http_static_module模块,负责客户端的静态页面请求处理并将对应的磁盘文件准备为响应内容输出。
output filter也称为filter模块,主要是负责对输出的内容进行处理,可以对输出进行修改。例如,可以实现对输出的所有html页面增加预定义的footbar一类的工作,或者对输出的图片的URL进行替换之类的工作。
upstreamupstream模块实现反向代理的功能,将真正的请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端。upstream模块是一种特殊的handler,只不过响应内容不是真正由自己产生的,而是从后端服务器上读取的
load-balancer负载均衡模块,实现特定的算法,在众多的后端服务器中,选择一个服务器出来作为某个请求的转发服务器。

nginx的请求处理模型

nginx使用一个多进程模型来对外提供服务,实际上的业务处理逻辑都在worker进程中有一个函数,执行无限循环,不断处理收到的来自客户端的请求,并进行处理,直到整个nginx服务被停止。

worker进程中,ngx_worker_process_cycle()函数就是这个无限循环的处理函数。在这个函数中,一个请求的简单处理流程如下:

  1. 操作系统提供的机制(例如epoll, kqueue等)产生相关的事件。
  2. 接收和处理这些事件,如是接受到数据,则产生更高层的request对象。
  3. 处理request的header和body。
  4. 产生响应,并发送回客户端。 完成request的处理。
  5. 重新初始化定时器及其他事件。
Nginx 变量

Nginx 变量的创建只能发生在 Nginx 配置加载的时候,或者说 Nginx 启动的时候;而赋值操作则只会发生在请求实际处理的时候。这意味着不创建而直接使用变量会导致启动失败,同时也意味着我们无法在请求处理时动态地创建新的 Nginx 变量。

  1. Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server 配置块
  2. 这样子做的好处是,启动的时候就可以判断每个请求的内存空间,方便申请释放。(个人理解)
Nginx处理请求的11个阶段

Nginx 变量上下文,随着请求开始而生成,请求结束可释放。Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log。

阶段触发解释
post-read读取并解析完请求头它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值
例如:使用了 ngx_realip 模块提供的 set_real_ip_from 和 real_ip_header 这两条配置指令
server-rewriteserver 配置块中的 set 指令等
find-config不支持自定义处理程序,由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作
rewritelocation 配置块 set 指令等
post-rewrite不支持自定义处理程序,由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作(如果 rewrite 阶段有此要求的话)
例如:通过 rewrite 指令把当前请求的 URI 无条件地改写为 /bar,同时发起一个“内部跳转”,最终跳进了 location /bar 中。
preaccess标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段,前者可以控制请求的访问频度,而后者可以限制访问的并发度。
access标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。
post-access不支持自定义处理程序,post-access 阶段主要用于配合 access 阶段实现标准 ngx_http_core 模块提供的配置指令 satisfy 的功能
try-files不支持自定义处理程序,专门用于实现标准配置指令 try_files 的功能
content读取并解析完请求体这个阶段的配置指令一般都肩负着生成“内容”(content)并输出 HTTP 响应的使命。正因为其重要性,这个阶段的配置指令也异常丰富。
log比如记录访问量/统计平均响应时间
  • nginx的代码执行顺序,和你指令所在的周期有关,和书写顺序无太大关系,如果同周期指令可视为乱序。
  • 对于运行在 find-config 阶段之前的 post-read 和 server-rewrite 阶段来说,请求并没有与任何 location 配置块相关联, 因此只有server 配置块以及更外层作用域中的配置指令才会起作用。
  • post-rewrite“内部跳转”本质上其实就是把当前的请求处理阶段强行倒退到 find-config 阶段,以便重新进行请求 URI 与 location 配置块的配对。
  • satisfy 的功能, 对于多个 Nginx 模块注册在 access 阶段的处理程序, satisfy 配置指令可以用于控制它们彼此之间的协作方式。比如模块 A 和 B 都在 access 阶段注册了与访问控制相关的处理程序,那就有两种协作方式,一是模块 A 和模块 B 都得通过验证才算通过,二是模块 A 和模块 B 只要其中任一个通过验证就算通过。第一种协作方式称为 all 方式(或者说“与关系”),第二种方式则被称为 any 方式(或者说“或关系”)。默认情况下,Nginx 使用的是 all 方式。
  • try_files 指令接受两个以上任意数量的参数,每个参数都指定了一个 URI. 这里假设配置了 N 个参数,则 Nginx 会在 try-files 阶段,依次把前 N-1 个参数映射为文件系统上的对象(文件或者目录),然后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在,就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI(但不会包含末尾的斜杠字符,也不会发生 “内部跳转”)。如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.通过 root 配置指令所指定的“文档根目录”进行映射。例如,当“文档根目录”是 /var/www/ 的时候,请求 URI /foo/bar 会被映射为文件 /var/www/foo/bar,而请求 URI /foo/baz/ 则会被映射为目录 /var/www/foo/baz/. 注意这里是如何通过 URI 末尾的斜杠字符是否存在来区分“目录”和“文件”的。

nginx衍生版本

Openresty和Tengine基于 Nginx 的两个衍生版本。

  • Openresty:是基于Ngnix和Lua的高性能web平台,内部集成精良的Lua库、第三方模块、依赖项。用于方便搭建能够处理高并发、扩展性极高的动态web应用、web服务、动态网关。
  • Tengine:融入了因淘宝自身的一些业务带来的新功能(如,dubbo协议的)

Openresty趋向于把复杂的C语言的nginx模块开发引向lua脚本。使nginx模块开发变的更加简单,易用。另外基于Openresty的网关产品 Apache APISIX, 是一个动态、实时、高性能的 API 网关,基于 Nginx 网络库和 etcd 实现, 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。

主要参考

nginx平台初探(100%)
agentzh 的 Nginx 教程
Openresty 官网
Tengine 官网
Apache APISIX
Nginx中文文档

### 回答1: 《nginx完全开发指南》是一本介绍nginx的操作和开发的详细指南。Nginx是一款开源的高性能Web服务器和反向代理服务器,它的设计极为简洁,可以快速高效地处理大量的Web请求。本书详细介绍了Nginx的运行原理和基本配置、常见模块、反向代理、负载均衡、HTTPS部署、Nginx扩展开发等方面的知识。其中,重点介绍了Nginx的C语言扩展开发,包含了连接池、内存池、数据缓存、日志模块、定时器等核心功能的实现。同时,本书还涵盖了Nginx在高并发、高性能场景下的优化方法,包括TCP参数调整、负载均衡算法、后端服务器连接池等方面的内容。 对于参与Web开发的工程师和运维人员而言,《nginx完全开发指南》是一本非常实用的技术指南。书中除了详细介绍了Nginx的基本功能和应用场景外,还深入探讨了Nginx扩展开发的核心理念和实现方法,让读者深入理解Nginx的工作原理,从而更好地适应不同的需求。此外,书中的实例代码和案例分析,也能让读者在理论基础上更好地掌握Nginx的实际应用,提高自己的技能水平。 总之,《nginx完全开发指南》是一本非常全面的Nginx技术指南,对于想要深入了解Nginx的开发和优化的读者而言,是一本不可多得的技术参考书籍。 ### 回答2: 《nginx完全开发指南》是一本关于Web服务器Nginx的实践指南,详细介绍了Nginx的原理、安装配置、可行性和高级应用。本书涵盖了大量的实用技巧和实例,易于新手入门,对于有经验的开发人员来说也是一本不可多得的参考手册。 本书首先详细介绍了Nginx的概念、安装和配置,包括Nginx的架构、事件模型、编译安装和运行配置。接着,本书详细介绍了Nginx的HTTP服务器、反向代理和负载均衡,以及如何使用Nginx搭建多个虚拟主机和动态Web站点。 同时,本书也介绍了安全、缓存和公共网关接口等高级主题,以及如何使用Nginx进行日志处理、性能优化和Web服务监测。此外,本书还涉及了Nginx与PHP、Python、Ruby等语言的集成,以及与MySQL和Redis等数据库的交互。 总之,《nginx完全开发指南》对Nginx的开发和应用提供了全面的指导和实例,既适合初学者,也适合有经验的开发人员。同时,该书结合了开发和实践,为读者提供了深入了解Nginx并灵活应用的能力和方法。 ### 回答3: 《Nginx完全开发指南》是一本面向Linux系统管理员和开发人员的实用指南,适合初学者和有一定经验的人员学习使用。本书通过详细讲解Nginx服务器的安装、配置、请求处理等方面的内容,让读者掌握使用Nginx搭建Web服务器的技能。 该书首先介绍了Nginx服务器的概述和整体架构,接着深入探讨了Nginx的安装和配置方法,包括如何进行源码编译、模块加载、运行环境配置等方面的内容。其次,该书详细分析了Nginx服务器的请求处理机制和动态模块的编写方法,帮助读者深入了解Nginx服务器的运行原理和核心功能。 此外,本书还介绍了Nginx服务器的高级应用和优化技巧,例如反向代理、负载均衡、SSL加密、缓存控制等方面的内容。这些内容可以帮助读者在实际工作中更好地运用Nginx服务器,提高服务器的性能和可靠性。 总体来说,《Nginx完全开发指南》是一本非常实用的书籍,内容深入浅出,易于理解,适合初学者和有一定经验的读者阅读和学习。对于需要使用Nginx服务器搭建Web应用的开发人员和系统管理员来说,该书是一本不可多得的好书。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值