分布式系列之聊聊Nginx实现原理

news2024/11/22 18:49:06

Nginx作为开源的轻量级的HTTP服务器,广泛应用于分布式应用架构中。本文简要介绍了Nginx的特点及使用场景、Nginx的进程模型和请求处理流程,并结合不同场景进行配置,对Nginx的架构和实现原理有个初步的了解。


1、Nginx是什么

Nginx(engine X)是一个开源的轻量级的HTTP服务器,能够提供高性能的HTTP和反向代理服务。与传统的Apache服务器相比,在性能上Nginx占用系统资源更小、支持高并发,访问效率更高;在功能上,Nginx不仅作为Web服务软件,还适用于反向代理、负载均衡等场景;在安装配置上,Nginx更为简单、灵活。Nginx因为并发性能和资源占用上的优势,已经广泛用于大中型互联网企业。

1.1 Nginx特点

Nginx具有以下特点:

  • 支持高并发:Nginx是专门为性能优化而开发的,采用内核Poll模型,单机能够支持几万以上的并发连接
  • 低资源消耗:Nginx采取了分阶段资源分配技术,使得CPU与内存的占用率非常低。一般1万个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗几MB内存
  • 高拓展性:设计极具扩展性,由多个不同功能、不同层次、不同类型且耦合度极低的模块组成
  • 高可用性:Nginx支持热部署,其中的master管理进程与worker工作进程的分离设计;启动速度特别迅速,因此可以在不间断服务的情况下,对软件版本或者配置进行升级,即使运行数月也无需重新启动,几乎可以做到7x24小时不间断地运行
  • 丰富的使用场景:可以作为Web服务端、HTTP反向代理、负载均衡和前端缓存服务等场景使用
  • 开源协议:使用BSD许可协议,免费使用,且可修改源码
1.2 Nginx使用场景
1.2.1 反向代理

代理服务器一般指代局域网内部的机器通过代理服务发送请求到互联网上的服务器,代理服务器一般作用于客户端。代理服务器是介于客户端和Web服务器之间的服务器,客户端首先与代理服务器创建连接,然后根据代理服务器所使用的代理协议,请求对目标服务器创建连接、或则获得目标服务器的指定资源。

在这里插入图片描述

  • 正向代理:为了从原始服务器取的内容,客户端向代理发送一个请求并指定目标(Web服务器),然后代理向Web服务器转交请求并将获得的内容返回给客户端,客户端必须要进行一些特别的设置才能使用正向代理。
    • 像VPN就是正向代理,一般在浏览器中配置代理服务器的相关信息。
    • 正向代理中代理的对象是客户端,代理服务器和客户端属于同一个LAN,对服务器端来说是透明的。
  • 反向代理:客户端发送请求到代理服务器,由代理服务器转发给相应的Web服务器进行处理,最终返回结果给客户端。
    • 像Nginx就是反向代理服务器软件,对客户端暴露的其实是一个VIP,不是真实的Web服务器的IP
    • 反向代理的是对象是Web服务器端,代理服务器和Web服务端属于同一个LAN,对客户端来说是透明的。

使用反向代理的好处是客户端不需要任何配置就可以访问,对外暴露的是代理服务器的地址隐藏了真实服务器的地址,客户端只需要把请求发送给代理服务器,由代理服务器去选择后端的Web服务器,获取到数据后再返回给客户端。

1.2.2 负载均衡

负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

简而言之,单个Web应用服务器不能承受日益增长的并发量请求,因此需要不断扩展web服务器来支撑高并发请求,根据不同的负载均衡策略将请求分配到各个服务器上。Nginx支持三种不同的负载均衡策略:

  • 轮询:每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉能够被自动剔除。轮询算法适合服务器配置相当,无状态且短平快的服务使用。
  • weight权重:指定轮询的几率,weight和后端的访问比例成比例,weight权重越高比例越大。通常用于后端服务器配置不均的情况。
  • ip_hash:上面两种算法存在一个问题是就是无法做到会话保持,当用户登录到服务器上后,第二次请求的时候会被定位到服务器集群中的某一个,那么已经登录到某个服务器上的用户会重新定位到另一台,之前的登录信息会丢失。ip_hash算法可以解决这个问题,当用户再次访问请求时,会通过hash算法自动定位到已经登录的服务器上,这样每个客户端可以固定在某个web服务器上,解决客户端session的问题。

在这里插入图片描述

1.2.3 动静分离

动静分离技术是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,将静态文件放在一个单独的web服务器上,加快解析速度,降低原来单个服务器的压力。在Nginx的配置中,在server{}段中加入带正则匹配的location来指定匹配项针对PHP的动静分离:静态页面交给Nginx处理,动态页面交给PHP-FPM模块或Apache处理。

在这里插入图片描述

1.3 Nginx功能模块说明

Nginx由内核和模块组成,其中内核在设计上非常简洁,完成的工作非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。

1.3.1 Nginx模块分类

Nginx的模块从结构上分为核心模块、基础模块和第三方模块,其中用户根据自己的需要开发的模块都属于第三方模块:

  • 核心模块:HTTP模块、EVENT模块和MAIL模块
  • 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块,
  • 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块。

在这里插入图片描述

1.3.2 Nginx模块功能

在这里插入图片描述

Nginx模块常规的HTTP请求和响应的过程如上图所示,Nginx模块从功能上分为以下三类:

  • Handlers处理器模块:此类模块直接处理请求,并进行输出内容和修改headers信息等操作。Handlers处理器模块一般只能有一个。
  • Filters过滤器模块:此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。
  • Proxies代理类模块:此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。

Nginx本身处理的工作很少,当它接到一个HTTP请求时,通过查找配置文件将此次请求映射到一个location block,而此location中所配置的各个指令则会启动不同的模块去完成工作。

2、Nginx架构解析

2.1 Nginx进程模型

在这里插入图片描述

Nginx默认采用多进程工作方式,在Nginx启动后,会运行一个master进程和多个worker进程。

  • master主要用来管理worker进程,充当整个进程组与用户的交互接口,同时对进程进行监护,实现worker进程的重启服务、平滑升级、更换日志文件、配置文件实时生效等功能;
  • worker进程用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。一个请求只能在一个worker进程中处理,一个worker进程不可能处理其它worker进程中的请求。

另外在Nginx架构中还有Cache Loader和Cache Manager进程,Cache Loader进程加载缓存索引文件信息;Cache Manager进程管理磁盘的缓存大小,超过预定值大小后最小使用的数据将被删除。

2.1.1 Master管理进程

Master进程主要用来管理worker进程,具体包括如下4个主要功能:

  • 接收来自外界的信号;
  • 向各worker进程发送信号;
  • 监控woker进程的运行状态;
  • 当woker进程退出后(异常情况下),会自动重新启动新的woker进程。

Master进程接受到命令重启Nginx进程(./nginx -s reload),会按照以下流程:

  1. 首先master进程在收到重启命令后,会先重新加载配置文件,然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。
  2. 新的worker进程在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且处理完当前进程中的所有未处理完的请求后,再退出。
2.1.2 Worker工作进程

Worker工作进程之间是对等的,每个进程处理请求的机会也是一样的。Nginx采用异步非阻塞的方式来处理网络事件,具体流程如下:

  1. 接收请求:首先,每个worker进程都是从master进程fork过来,在master进程建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。
    1. 所有worker进程的listenfd会在新连接到来时变得可读,每个work进程都可以去accept这个socket(listenfd)。
    2. 当一个client连接到来时,所有accept的work进程都会受到通知,但只有一个进程可以accept成功,其它的则会accept失败。
    3. 为保证只有一个进程处理该连接,Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接。
    4. 所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。
  2. 处理请求:当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。

由上可以看出,一个请求完全由worker进程处理,并且只在一个worker进程中处理。

2.2 Nginx请求处理流程

在这里插入图片描述

Nginx工作进程会监听套接字上的事件(accept_mutex和kernel socketsharding),来决定什么时候开始工作。事件是由新的连接初始化的,这些连接会被分配给状态机,Nginx中有三大类状态机:处理应用层的HTTP状态机、处理TCP/UDP的4层的传输层状态机和处理邮件的MAIL状态机,其中HTTP状态机最为常见。

在多种流量进入Nginx后,Nginx的三种状态机在Nginx解析出请求后,会动用线程池处理调用,将静态资源、反向代理、错误日志等信息分别导向不同的出口,比如fastcgi会导向PHP处理、html会导向nginx处理,并将处理请求日志记录到本地或远程服务器中。

2.3 Nginx多进程IO模型
2.3.1 Nginx多进程模型

Nginx默认使用多进程的工作方式,相比较多线程的方式,有以下好处:

  1. 首先,对于每个worker进程来说,独立的进程不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多;
  2. 其次,采用独立的进程,可以让进程之间相互不会影响,一个进程退出后,其它进程还在工作,服务也不会中断,master进程则很快启动新的worker进程;
  3. 再次,为Nginx热部署提供了支持。在修改配置文件nginx.conf后,重新生成新的worker进程,新的worker进程会以新的配置处理请求,而老的worker进程,等把以前的请求处理完成以后,kill掉就可以。
2.3.2 Nginx异步非阻塞事件模型

异步非阻塞事件是怎么回事?先看一个请求的完整过程,首先请求过来建立连接,然后再接收数据再发送数据,具体到系统层就是IO读写事件。当读写事件没有准备好,如果不采用非阻塞的方式,就得阻塞调用,阻塞调用会进入内核等待,导致CPU资源被其它进程占用。当并发请求越大时,等待的事件越多,CPU利用不上去,并发也上不去。因此Nginx使用非阻塞的事件模型,系统中事件模型有很多中,比如select/poll/kqueue/epoll等,Nginx采用epoll模型。Epoll模型基于事件驱动机制,可以监控多个事件是否准备完毕,如果可以,就放入epoll队列,这个过程是异步的,worker进程只需要从epoll队列循环处理即可。Epoll调用过程如下图所示:

在这里插入图片描述

3、Nginx部署与配置

3.1 Nginx环境部署

1)下载安装包,官网链接https://nginx.org/en/download.html

2)解压安装包

[root@tango-rac01 src]# tar -xzvf nginx-1.22.1.tar.gz

3)编译配置

[root@tango-rac01 nginx-1.22.1]# ./configure
[root@tango-rac01 nginx-1.22.1]# make
[root@tango-rac01 nginx-1.22.1]# whereis nginx
nginx: /usr/local/nginx

4)启动Nginx

[root@tango-rac01 nginx-1.22.1]# cd /usr/local/nginx/
[root@tango-rac01 nginx]# ./sbin/nginx
[root@tango-rac01 nginx]# ss -antl
State       Recv-Q Send-Q                                        Local Address:Port                                                       Peer Address:Port                              
LISTEN      0      511                                                       *:80                                                                    *:*                  

5)访问页面ip:80

在这里插入图片描述

3.2 Nginx不同场景配置
3.2.1 Nginx配置文件介绍
...              #全局块

events {         #events块
   ...
}

http      #http块
{
    ...   #http全局块
    server        #server块
    { 
        ...       #server全局块
        location [PATTERN]   #location块
        {
            ...
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     #http全局块
}
  • 全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
  • events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
  • http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
  • server块:配置虚拟主机的相关参数,一个http中可以有多个server。
  • location块:配置请求的路由,以及各种页面的处理情况。
3.2.2 反向代理配置

1)简单配置如下:

	server {
        keepalive_requests 120;
        listen       80;
        server_name  192.168.112.135; 
        location ~ /news/ {
           proxy_pass  http://192.168.112.101:8080; 
        } 
        location ~ /prod/ {
           proxy_pass  http://192.168.112.101:8081; 
        } 
    }

访问http:// 192.168.112.135:80/news/时会跳转到http://192.168.112.101:8080,访问http:// 192.168.112.135:80/prod/时会跳转到http://192.168.112.101:8081

3.2.3 负载均衡配置

1)配置如下:

upstream myServer {    
    server 192.168.112.101:8080 down;   
    server 192.168.112.101:8090 weight=2;   
    server 192.168.112.101:6060;   
    server 192.168.112.101:7070 backup;   
}
#指定负载均衡策略为ip_hash
upstream myServer {
    ip_hash
    server 192.168.112.101:8080;   
server 192.168.112.101:6060;   
}
  • down:表示当前的server暂时不参与负载
  • Weight:默认为1,weight越大,负载的权重就越大。
  • max_fails:允许请求失败的次数默认为1,当超过最大次数时,返回proxy_next_upstream 模块定义的错误
  • fail_timeout:max_fails 次失败后,暂停的时间。
  • Backup:其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
3.2.4 动静分离配置

1)配置如下:

   server {
       listen       10000;
       server_name  localhost;
      
      #拦截后台请求
      location / {
        proxy_pass http:// 192.168.112.101:8888;
        proxy_set_header X-Real-IP $remote_addr;
      }

      #拦截静态资源
      location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|js|css)$ {
        root /static/;
        autoindex on;
       }
    }

上述配置中,访问静态资源在根目录的/static/下。

4、总结

Nginx作为开源的轻量级的HTTP服务器,广泛应用于分布式应用架构中。本文简要介绍了Nginx的特点及使用场景、Nginx的进程模型和请求处理流程,并结合不同场景进行配置,对Nginx的架构和实现原理有个初步的了解。


参考资料:

  1. https://www.nginx.com/resources/library/infographic-inside-nginx/
  2. https://blog.csdn.net/hguisu/article/details/8930668
  3. https://blog.csdn.net/khuangliang/article/details/122345060
  4. https://blog.csdn.net/qq_42511550/article/details/125054697

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Echarts之甘特图type: ‘custom‘参数详解

甘特图 const groupData XEUtils.groupBy(data, "eqpName"); //分组后的数据 const yAxisData Object.keys(groupData); const seriesData Object.keys(groupData).map((item, index) > {let arr [];groupData[item].forEach((GItem) > {arr.push([index,f…

Graphviz安装向导及入门指南

目录 1、首先在官网下载graphviz 2、安装。 3、测试并在Windows命令行中使用 4、在Python中使用 5、在自带的gvedit.exe 程序中使用 6、在语雀中使用 7、绘制一棵简单的二叉树 8、详细语法介绍 8.1 带标签 8.2 修改方框颜色和形状 8.3子视图 8.4 结构视图 8.5 …

【网络安全】Centos7安装杀毒软件----ClamAV

一、ClamAV介绍 Clam AntiVirus是一个Linux系统上使用的反病毒软件包。主要应用于邮件服务器,采用多线程后台操作,可以自动升级病毒库。 二、安装 1.下载rpm wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2.升级epe…

4.1、网络层概述

1、主要任务 网络层的主要任务是实现网络互连\color{red}实现网络互连实现网络互连,进而实现数据包在各网路之间的传输\color{red}实现数据包在各网路之间的传输实现数据包在各网路之间的传输 例如: 这些异构型网络若只是需要各自内部通信&#xff0c…

高质量发展指标构建:全国各省高质量发展需求(2014-2021年)

高质量发展是坚持更高层次和更高水平对外开放的发展。中国改革开放四十年的实践充分证明,不断扩大对外开放是推动中国经济社会发展的重要动力,是实现国家繁荣富强的根本出路。因此,在中国经济发展的新时代,推动新一轮高水平开放&a…

docker logs实时查看日志tail

docker logs实时查看日志tail docker logs -f -t --since="2017-05-31" --tail=10 container说明: --since : 指定输出日志开始日期。 -f : 查看实时日志 -t : 查看日志产生的时间戳 -tail=10 : 查看最后的10条日志。 container : 容器名docker logs -f --until=2s说…

Docker常用操作命令总结(一)

文章目录一、Docker的应用场景二、Docker 的优点三、Docker 架构四、安装Docker1、更新 apt 包索引2、安装docker3、安装完成之后,运行命令sudo docker info,检查安装状态4、有可能,第一次需要手动启动服务.就需要执行下面的命令,…

LabVIEW如何减少下一代测试系统中的硬件过时4

LabVIEW如何减少下一代测试系统中的硬件过时4 DSSP Class Definition DSSP父类定义有三种不同类型的函数:仅父类、公共类和基于度量的函数。DSSP父类,DSSP.Lvclass包含所有子类函数的超集,加上父类特有的一些函数。DSSP父类的单个子实例(例如AgSigGen.…

2022年总结(2022年1月1日至2022年12月25日)

前言 时光飞逝,又到了一年一度的年终总结的时间了,2022年充满磨难的一年,悲哉,痛哉~~ 但对于我而言,其实还好,基本无太大影响,黄金单身汉,一人吃饱,全家不饿~&#xff…

spring之手写框架

文章目录前言一、手写spring框架之核心接口实现二、手写spring框架之实例化Bean三、手写spring框架之获取所有set方法四、手写spring框架之给属性赋值4.1 非简单类型属性赋值4.2 简单类型属性赋值附:前言 Spring IoC容器的实现原理:工厂模式解析XML反射…

学习性能所必须的知识之算法

什么是算法? 通过有效地缩小查找范围,只需要很少的次数就能很快速的找到需要的数字,这样的策略或方法就称为“算法”。 算法的好坏对性能有很大的影响。 学习算法的窍门 掌握算法优点与缺陷,“折中”是一个很重要的思维通过在图上推演来思考评价算法的指标 通过复杂度(…

各种型号西门子PLC所支持的通信协议小结

西门子PLC有4大类,几十个型号类型,PLC不同所支持的通讯协议也不相同。 按照大类型来划分,具体可分为串口协议和以太网通信协议两大类。 串口协议主要有:MODBUS RTU 通信协议;PROFIBUS 通信协议;USS通信协…

疫情信息管理系统(附源代码及数据库)

本系统是一个可以对各种疫情进行管理的系统,管理员可以直接对居民、住户进行统一的管理,这样就能在疫情期间大大减轻了管理者的工作量,使管理社区的渠道更加的方便。其主要功能有:登录功能,公告的发布,到访…

2022, 6年技术路, 后疫情时代复盘

专注 聚焦 持续复盘写下你一年的希望...又到了每年一度的复盘时间。转眼一想, 做技术已经 6 年了。说实话,有点疲惫了。今年整个互联网行业都不好过, 加上疫情的反复不断, 从耳边流出了很多裁员的信息, 股市也比较低迷, 身处底层的我们只能夹缝生存。但是, 我又是…

【MySQL基础教程】DQL语句详细介绍

前言 本文为 【MySQL基础教程】DQL语句 相关内容介绍,下边具体将对DQL语句基本语法,基础查询,条件查询,聚合函数,分组查询,排序查询,分页查询,相关案例,执行顺序等进行详…

Elasticsearch 核心技术(二):elasticsearch-head 插件安装和使用

❤️ 个人主页:水滴技术 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 🌸 订阅专栏:大数据核心技术从入门到精通 文章目录一、安装方式二、下载 head 插件三、安装 head 插件四、运行 head 插件五、使用…

服务器硬件规格常用查看命令——网卡相关命令

lspci 使用lspci命令可以显示系统中的PCI总线和连接到它们的设备信息,在默认情况下,显示一个简短格式的设备列表。但是可以使用“lspci -vvx”或“lspci -vvxxx”显示更加详细的设备信息,在这些信息中包含了PCI设备驱动程序或lspci本身的错误…

GitHub与微信开启“秘密扫描”计划,来确保数据安全

近日GitHub 官方博客更是宣布:" 腾讯微信现在是 GitHub 秘密扫描合作伙伴。" “秘密扫描”是Github发起的一个计划,可别被它名字吓到了,它并不是说秘密的扫描用户的隐私数据,而是和微信合作发起,防止微信开…

Redhat7上安装Red Hat Developer Toolset并自由切换gcc和g++的版本

Redhat7上安装Red Hat Developer Toolset并自由切换gcc和g的版本一、Red Hat Developer Toolset 概述二、使用Red Hat Software Collections2.1 获取pool ID2.2 将pool ID 附加到本地系统中2.3 获取仓库列表2.4 使能上述仓库三、安装 Red Hat Developer Toolset四、升级Red Hat…

大数据分析案例-基于决策树算法构建员工离职预测模型

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…