当前位置:网站首页 > 技术博客 > 正文

深入理解nginx模块开发与架构解析



image.png

 是开源、高性能、高可靠的  和反向代理服务器,而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是  最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数,最重要的是,  是免费的并可以商业化,配置使用也比较简单。






  • 高并发、高性能;
  • 模块化架构使得它的扩展性非常好;
  • 异步非阻塞的事件驱动模型这点和  相似;
  • 相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性;
  • 热部署、平滑升级;
  • 完全开源,生态繁荣;

Nginx 的最重要的几个使用场景:

  1. 静态资源服务,通过本地文件系统提供服务;
  2. 反向代理服务,延伸出包括缓存、负载均衡等;
  3.  服务,  ;
 
  

安装完成后,通过  命令查看  的安装信息:

 
  

主要关注的文件夹有两个:

  1.  是子配置项存放处,  主配置文件会默认把这个文件夹中所有子配置项都引入;
  2.  静态文件都放在这个文件夹,也可以根据你自己的习惯放在其他地方;

 系统命令:

 
  

 应用程序命令:

 
  

 的典型配置示例:

 
  
  •  全局配置,对全局生效;
  •  配置影响  服务器与用户的网络连接;
  •  配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置;
  •  配置虚拟主机的相关参数,一个  块中可以有多个  块;
  •  用于配置匹配的  ;
  •  配置后端服务器具体地址,负载均衡配置不可或缺的部分;

指定运行  的  子进程的属主和属组,其中组可以不指定。

 
  

指定运行  主进程的  文件存放路径。

 
  

指定  子进程可以打开的最大文件句柄数。

 
  

指定  子进程异常终止后的  文件,用于记录分析问题。

 
  

指定  启动的  子进程数量。

 
  

将每个  子进程与我们的  物理核心绑定。

 
  

指定  子进程的  值,以调整运行  的优先级,通常设定为负值,以优先调用  。

 
  

指定  子进程优雅退出时的超时时间。

 
  

 子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降。

 
  

指定  的运行方式,前台还是后台,前台用于调试,后台用于生产。

 
  

 使用何种事件驱动模型。

 
  

子进程能够处理的最大并发连接数。

 
  

是否打开负载均衡互斥锁。

 
  

指定虚拟主机域名。

 
  

域名匹配的四种写法:

  • 精确匹配:  ;
  • 左侧通配:  ;
  • 右侧统配:  ;
  • 正则匹配:  ;

匹配优先级:精确匹配 > 左侧通配符匹配 > 右侧通配符匹配 > 正则表达式匹配

 
  
 
  

3、访问分析

  • 当访问  时,都可以被匹配上,因此选择优先级最高的“完全匹配”;
  • 当访问  时,会进行“左匹配”;
  • 当访问  时,会进行“右匹配”;
  • 当访问  时,会进行“左匹配”;
  • 当访问  时,会进行“右匹配”;
  • 当访问  时,会进行“正则匹配”;

指定静态资源目录位置,它可以写在  、  、  等配置中。

 
  

它也是指定静态资源目录位置,它只能写在  中。

 
  

[注意] 使用 alias 末尾一定要添加  ,并且它只能位于  中。

配置路径。

 
  

匹配规则:

  •  精确匹配;
  •  正则匹配,区分大小写;
  •  正则匹配,不区分大小写;
  •  匹配到即停止搜索;
 
  
 
  
  • 不带  当访问  时,  先找是否有  目录,如果有则找  目录下的  ;如果没有  目录,   则会找是否有  文件。
  • 带  当访问 时,  先找是否有  目录,如果有则找  目录下的  ,如果没有它也不会去找是否存在  文件。
 
  

根据指定正则表达式匹配规则,重写  。

 
  
  •  重写后的  发起新请求,再次进入  段,重试  的中的匹配;
  •  直接使用重写后的  ,不再匹配其它  中语句;
  •  返回302临时重定向;
  •  返回301永久重定向;
 
  

按照这个配置我们来分析:

  • 当访问  时,会自动帮我们重定向到 。
  • 当访问  时,第一步重写  为  ,找到  的  ,继续重写  为  ,找到  的  后,去  目录下寻找  静态资源。
 
  
  •  仅为变量时,值为空或以0开头字符串都会被当做  处理;
  •  或  相等或不等;
  •  正则匹配;
  •  非正则匹配;
  •  正则匹配,不区分大小写;
  •  或  检测文件存在或不存在;
  •  或  检测目录存在或不存在;
  •  或  检测文件、目录、符号链接等存在或不存在;
  •  或  检测文件可以执行或不可执行;
 
  

当访问  时,会进入  判断里面执行  命令。

 
  
变量名 含义   客户端  地址   客户端端口   服务端  地址   服务端端口   服务端协议   二进制格式的客户端  地址    连接的序号,递增    连接当前的请求数量   请求的URL,不包含参数   请求的URL,包含参数   协议名,  或     请求方法   全部请求的长度,包含请求行、请求头、请求体   全部参数字符串   获取特定参数值    中是否有参数,有的话返回  ,否则返回空   与  相同   请求信息中的  ,如果请求中没有   行,则在请求头中找,最后使用  中设置的  。   用户浏览器   从哪些链接过来的请求   每经过一层代理服务器,都会添加相应的信息   获取用户     处理请求已消耗的时间   是否开启了  ,是则返回  ,否则返回空   磁盘文件系统待访问文件的完整路径   由  和  规则生成的文件夹路径   返回响应时的速度上限值

实例演示  :

 
  

当我们访问   时,由于  中写了  方法,因此  浏览器会默认为我们下载一个文件,下面展示的就是下载的文件内容:

 
  

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

  • 反向代理*(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
  • 隐藏真实服务器;
  • 负载均衡便于横向扩充后端动态服务;
  • 动静分离,提升系统健壮性;

动静分离是指在  服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提示整个服务的访问性和可维护性。

未命名文件.png

一般来说,都需要将动态资源和静态资源分开,由于  的高并发和静态资源缓存等特性,经常将静态资源部署在  上。如果请求的是静态资源,直接到静态资源目录获取资源,如果是动态资源的请求,则利用反向代理的原理,把请求转发给对应后台应用去处理,从而实现动静分离。

使用前后端分离后,可以很大程度提升静态资源的访问速度,即使动态服务不可用,静态资源的访问也不会受到影响。












  • 轮询策略:默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
  • 最小连接数策略:将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
  • 最快响应时间策略:优先分配给响应时间最短的服务器。
  • 客户端  绑定策略:来自同一个  的请求永远只分配一台服务器,有效解决了动态网页存在的  共享问题。

在配置反向代理和负载均衡等等功能之前,有两个核心模块是我们必须要掌握的,这两个模块应该说是  应用配置中的核心,它们分别是:  、 。

 
  

在  内可使用的指令:

  •  定义上游服务器地址;
  •  定义共享内存,用于跨  子进程;
  •  对上游服务启用长连接;
  •  一个长连接最多请求  的个数;
  •  空闲情形下,一个长连接的超时时长;
  •  哈希负载均衡算法;
  •  依据  进行哈希计算的负载均衡算法;
  •  最少连接数负载均衡算法;
  •  最短响应时间负载均衡算法;
  •  随机负载均衡算法;

定义上游服务器地址。

 
  

 可选值:

  •  权重值,默认为1;
  •  上游服务器的最大并发连接数;
  •  服务器不可用的判定时间;
  •  服务器不可用的检查次数;
  •  备份服务器,仅当其他服务器都不可用时才会启用;
  •  标记服务器长期不可用,离线维护;

限制每个  子进程与上游服务器空闲长连接的最大数量。

 
  
 
  
 
  
 
  

用于配置代理服务器。

 
  

 参数原则

  1.  必须以  或  开头;
  2.  中可以携带变量;
  3.  中是否带  ,会直接影响发往上游请求的  ;
  1.  

这两种用法的区别就是带  和不带  ,在配置代理时它们的区别可大了:

  • 不带  意味着  不会修改用户  ,而是直接透传给上游的应用服务器;
  • 带  意味着  会修改用户  ,修改方法是将  后的  从用户  中删除;
 
  

分析:

  1. 用户请求  :  
  2. 请求到达  的  :  
  3. 请求到达上游应用服务器的  :  
 
  

分析:

  1. 用户请求  :  
  2. 请求到达  的  :  
  3. 请求到达上游应用服务器的  :  

这里为了演示更加接近实际,作者准备了两台云服务器,它们的公网  分别是:  与  。

我们把  服务器作为上游服务器,做如下配置:

 
  
 
  

本地机器要访问  域名,因此需要配置本地  ,通过命令: 进入配置文件,添加如下内容:

 
  

image.png

分析:




  1. 当访问  时通过  的配置找到  ;
  2. 因此访问地址变为  ;
  3. 连接到  服务器,找到  端口提供的  ;
  4. 通过  找到  资源,最终展示出来。

配置负载均衡主要是要使用  指令。

我们把  服务器作为上游服务器,做如下配置(  ):

 
  

配置完成后:

  1.  检测配置是否正确;
  2.  重启  服务器;
  3. 执行  命令查看端口是否被占用,从而判断  服务是否正确启动。
 
  

配置完成后重启  服务器。并且在需要访问的客户端配置好  和域名的映射关系。

 
  

通过制定关键字作为  ,基于  算法映射到特定的上游服务器中。关键字可以包含有变量、字符串。

 
  

 表示使用  变量作为  的  值,只要访问的  保持不变,就会一直分发给同一台服务器。

根据客户端的请求  进行判断,只要  地址不变就永远分配到同一台主机。它可以有效解决后台服务器  保持的问题。

 
  

各个  子进程通过读取共享内存的数据,来获取后端服务器的信息。来挑选一台当前已建立连接数最少的服务器进行分配请求。

 
  

示例:

 
  

最后你会发现,负载均衡的配置其实一点都不复杂。

缓存可以非常有效的提升性能,因此不论是客户端(浏览器),还是代理服务器(  ),乃至上游服务器都多少会涉及到缓存。可见缓存在每个环节都是非常重要的。下面让我们来学习  中如何设置缓存策略。

 
  

设置缓存文件的存放路径。

 
  

参数含义:

  •  缓存文件的存放路径;
  •  的目录层级;
  •  设置共享内存;
  •  在指定时间内没有被访问,缓存会被清理,默认10分钟;

设置缓存文件的  。

 
  

配置什么状态码可以被缓存,以及缓存时长。

 
  

定义相应保存到缓存的条件,如果字符串参数的至少一个值不为空且不等于“ 0”,则将不保存该响应到缓存。

 
  

定义条件,在该条件下将不会从缓存中获取响应。

 
  

它存储了缓存是否命中的信息,会设置在响应头信息中,在调试中非常有用。

 
  

我们把  服务器作为上游服务器,做如下配置(  ):

 
  

把  服务器作为代理服务器,做如下配置(  ):

 
  
 
  

在学习如何配置  之前,我们先来简单回顾下  的工作流程是怎么样的?它是如何进行加密保证安全的?

  1. 客户端(浏览器)访问  百度网站;
  2. 百度服务器返回  使用的  证书;
  3. 浏览器验证  证书是否为合法证书;
  4. 验证通过,证书合法,生成一串随机数并使用公钥(证书中提供的)进行加密;
  5. 发送公钥加密后的随机数给百度服务器;
  6. 百度服务器拿到密文,通过私钥进行解密,获取到随机数(公钥加密,私钥解密,反之也可以);
  7. 百度服务器把要发送给浏览器的内容,使用随机数进行加密后传输给浏览器;
  8. 此时浏览器可以使用随机数进行解密,获取到服务器的真实传输内容;

这就是  的基本运作原理,使用对称加密和非对称机密配合使用,保证传输内容的安全性。

关于HTTPS更多知识,可以查看作者的另外一篇文章《学习 HTTP 协议》。

 
  

先简单回顾下跨域究竟是怎么回事。

 
  

不同源会有如下限制:

  •  数据层面,同源策略限制了不同源的站点读取当前站点的  、  、  等数据。
  •  层面,同源策略限制了来自不同源的  脚本对当前  对象读和写的操作。
  • 网络层面,同源策略限制了通过  等方式将站点的数据发送给不同源的站点。

例如:

  • 前端  的域名为:  
  • 后端服务的域名为:  
 
  
 
  

其实也可以通过前端构建工具例如  、 等在打生产包时就做好  压缩,然后放到  服务器中,这样可以减少服务器的开销,加快访问速度。

关于  的实际应用就学习到这里,相信通过掌握了  核心配置以及实战配置,之后再遇到什么需求,我们也能轻松应对。接下来,让我们再深入一点学习下  的架构。

  •  用来管理子进程的,其本身并不真正处理用户请求。
    • 某个子进程  掉的话,它会向  进程发送一条消息,表明自己不可用了,此时  进程会去新起一个子进程。
    • 某个配置文件被修改了  进程会去通知  进程获取新的配置信息,这也就是我们所说的热部署。
  • 子进程间是通过共享内存的方式进行通信的。

 重载配置文件的流程:

  1. 向  进程发送  信号(  命令);
  2.  进程检查配置语法是否正确;
  3.  进程打开监听端口;
  4.  进程使用新的配置文件启动新的  子进程;
  5.  进程向老的  子进程发送  信号;
  6. 老的  进程关闭监听句柄,处理完当前连接后关闭进程;
  7. 整个过程  始终处于平稳运行中,实现了平滑升级,用户无感知;

  • 上一篇: okhttp+
  • 下一篇: 爬虫软件叫什么
  • 版权声明


    相关文章:

  • okhttp+2025-09-29 20:30:05
  • 循环队列的基本操作c语言2025-09-29 20:30:05
  • cglib api2025-09-29 20:30:05
  • 单片机c语言基础语句及详解2025-09-29 20:30:05
  • 背包问题的贪心算法2025-09-29 20:30:05
  • 爬虫软件叫什么2025-09-29 20:30:05
  • java工具类库2025-09-29 20:30:05
  • 适配器模式的实现原理2025-09-29 20:30:05
  • 交叉验证的作用2025-09-29 20:30:05
  • mysql8.0.23安装配置教程2025-09-29 20:30:05