1. Nginx概述
Nginx是一个轻量级的高性能HTTP反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如TCP、UDP、SMTP、HTTPS等。
1.1 Nginx基础架构
Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。
Nginx 的主进程和工作进程协同工作,主进程负责控制和管理工作进程,而工作进程负责实际的请求处理。这种多进程模型使得 Nginx 能够高效地处理大量并发连接,提供高性能和可扩展性。主进程和工作进程的分离还提高了服务器的稳定性,因为即使一个工作进程崩溃,其他工作进程仍然可以正常工作。
·管理进程、多工作进程设计优点:
1.充分利用多核机器,增强并发处理能力。
2.负载均衡:多个 worker 工作进程通过进程间通信来实现负载均衡,即一个请求到来时更容易被分配到负载较轻的 worker 工作进程中处理。
3.Master 监控并统一管理 worker 行为。在 worker 异常后,可以主动拉起 worker 进程,从而提升了系统的可靠性。并且由 Master 进程控制服务运行中的程序升级、配置项修改等操作,从而增强了整体的动态可扩展与热更的能力。
1.1.1 Master进程
主进程是 Nginx 的控制进程,通常以 nginx 进程的名称运行。Master进程管理工作进程的生命周期,包括启动、停止、重新加载配置和升级 Nginx 等操作。主进程会读取主配置文件(通常是 nginx.conf),解析配置并初始化各个工作进程。
在配置更改或升级时,主进程会启动新的工作进程,然后逐步停止旧的工作进程,以确保平滑的过渡。主进程还接收来自管理员的信号,可以用于重新加载配置、停止服务等操作。
1.1.2 Worker进程
工作进程是 Nginx 的实际请求处理者。主进程可以创建多个工作进程,每个工作进程是一个独立的操作系统进程,可以并行处理客户端请求。工作进程的数量由配置文件中的 worker_processes 指令决定。通常,根据服务器硬件和负载情况,可以设置多个工作进程以充分利用多核处理器。
每个工作进程监听一个或多个端口,接受来自客户端的连接请求,并处理这些请求。工作进程之间是相互独立的,不共享内存。工作进程通过事件驱动的方式处理连接和请求,支持高并发和非阻塞 I/O 操作。不会因为一个请求的阻塞而影响其他请求的处理。
·worker工作模式:
worker对于连接是采用争抢的模式,谁先抢到就先交给谁处理,如果想要重新更新配置,由于已经抢到任务的worker不会参与争抢,那些空闲的worker就会去争抢连接,拿到连接后会自动更新配置信息,当那些有任务的worker完成任务后,会自动更新配置,这样就实现了无缝热部署。由于每个worker是独立的进程,如果有其中的一个worker出现问题,并不会影响其它worker继续进行争抢,在实现请求的过程,不会造成服务中断,建议worker数和服务器的CPU数相等是最为适宜的。
1.2 Nginx主要特性
Ngnix具有以下特性:
1. 更快的响应速度。在正常情况下,单次请求会得到更快的响应;另一方面,在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请求。
2. 高扩展性。Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须在意其他。Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模 块还是第三方模块都是如此。这使得第三方模块一样具备极其优秀的性能,充分利用Nginx的高并发特性。
3. 高可靠性。Nginx的高可靠性来自于其核心框架代码的优秀设计、模块设计 的简单性;另外,官方提供的常用模块都非常稳定,每个worker进程相 对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker 子进程提供服务。
4. 低内存消耗。Nginx的设计优化使其占用较少的内存和CPU资源,适用于高流量的Web应用和服务器。一般情况下,10000个非活跃的HTTP Keep-Alive连接在Nginx中仅 消耗2.5MB的内存,这是Nginx支持高并发连接的基础。
5. 高并发连接能力。理论上,Nginx支持的并发连接上限取决于多个因素,包括硬件、操作系统和配置。
2. Nginx安装
2.1 Nginx目录结构
/nginx-1.24.0
├── client_body_temp
├── conf # Nginx的主配置文件所在的目录
│ ├── fastcgi.conf # fastcgi相关参数的配置文件
│ ├── fastcgi.conf.default # fastcgi的默认配置文件
│ ├── fastcgi_params # fastcgi参数文件
│ ├── fastcgi_params.default
│ ├── koi-utf
│ ├── koi-win
│ ├── mime.types # 媒体类型
│ ├── mime.types.default
│ ├── nginx.conf # Nginx的主配置文件
│ ├── nginx.conf.default # Nginx的备份配置文件
│ ├── scgi_params
│ ├── scgi_params.default
│ ├── uwsgi_params
│ ├── uwsgi_params.default
│ └── win-utf
├── fastcgi_temp
├── html # 默认站点目录
│ ├── 50x.html # 错误页面优雅替代显示文件
│ └── index.html # 默认的首页文件,在实际环境中,大家习惯用
├── logs # 日志文件目录
│ ├── access.log # 访问日志文件
│ ├── error.log # 错误日志文件
│ └── nginx.pid # Nginx的PID文件,Nginx进程启动后,这个文件会随着Nginx启动而产生
├── proxy_temp
├── sbin # Nginx的二进制文件目录
│ └── nginx # Nginx的二进制文件
├── scgi_temp
└── uwsgi_temp
主要的目录文件有:conf 配置目录、html静态文件、logs日志目录、sbin执行文件。
2.2 编译与执行
2.2.1 Nginx必备库
- PCRE函数库
PCRE函数库用于解析正则表达式。如果在配置文件nginx.conf里使用了正则表达式,那么在编译 Nginx时就必须把PCRE库编译进Nginx,因为Nginx的HTTP模块要靠它来解析正则表达式。 - zlib库
zlib库用于对HTTP包的内容做gzip格式的压缩,如果我们在 nginx.conf里配置了gzip on,并指定对于某些类型(content-type)的 HTTP响应使用gzip来进行压缩以减少网络传输量,那么,在编译时就 必须把zlib编译进Nginx。 - OpenSSL
需要OpenSSL库来支持安全通信和加密功能,特别是在处理HTTPS(加密的HTTP)请求时。
a) SSL/TLS支持:OpenSSL用于在客户端和服务器之间建立加密通信,以保护数据的机密性和完整性。Nginx需要OpenSSL来处理HTTPS请求,从而使得通过HTTPS协议传输的数据能够被加密和解密。
b) 数字证书管理:OpenSSL库提供数字证书的创建、管理和验证功能。在HTTPS通信中,服务器需要使用数字证书来验证身份,并将其证书提供给客户端。客户端使用服务器的证书来验证服务器的真实性,并进行密钥协商。Nginx使用OpenSSL来支持这些数字证书操作。
c) 加密算法:OpenSSL实现了多种加密算法,用于加密和解密数据。Nginx可以使用这些加密算法来保护数据的机密性。这对于确保数据在传输过程中不被窃取或篡改至关重要。
d) HTTPS性能:Nginx通过与OpenSSL集成,能够有效地处理大量的HTTPS连接,因为OpenSSL本身也经过了高度优化。这使得Nginx成为一个流行的HTTPS服务器和反向代理服务器。
2.2.2 Nginx源码编译
通过指令将Ngnix压缩包解压到指定文件夹。
指令:tar -xvf nginx-1.24.0.tar.g
-x:解压缩文件。
-v:详细输出,可以看到解压的过程。
-f:后面紧跟着要解压的文件名。
进入nginx-1.24.0目录下执行:./configure、make、make install三行指令。
1.configure:configure命令检测操作系统内核和已经安装的软件,参数的解析,中间目录的生成以及根据各种参数生成一些C源码文件、Makefile文件等。
2.make:make命令根据configure命令生成的Makefile文件编译Nginx工程,并
生成目标文件、最终的二进制文件。
3.make install命令:根据configure执行时的参数将Nginx部署到指定的安
装目录,包括相关目录的建立和二进制文件、配置文件的复制。
./configure命令执行成功后,生成objs目录,生成文件如下,
· Ngx_module数组:
ngx_modules是非常关键的数组,它指明了每个模块在Nginx中的优
先级,当一个请求同时符合多个模块的处理规则时,将按照它们在
ngx_modules数组中的顺序选择最靠前的模块优先处理。对于HTTP过滤
模块而言则是相反的,因为HTTP框架在初始化时,会在ngx_modules数
组中将过滤模块按先后顺序向过滤链表中添加,但每次都是添加到链表
的表头,因此,对HTTP过滤模块而言,在ngx_modules数组中越是靠后
的模块反而会首先处理HTTP响应。
· 参数-v显示Nginx的版本信息;
· 参数-V显示编译配置编译阶段信息以及Nginx的版本信息;
· 参数-t测试配置文件是否正确。
· 参数-s stop强制停止Ngnix服务。
Nginx程序通过nginx.pid文件中得 到master进程的进程ID,再向运行中的master进程发送TERM信号来快速 地关闭Nginx服务。
1. Nginx启动:./nginx
2. Nginx停止:./nginx -s stop
3. 如果用户修改了nginx.conf,需要进行刷新:./nginx -s reload
2.3 Nginx核心配置
nginx.conf 是 Nginx 主要的配置文件,它定义了 Nginx 服务器的行为和各种设置。这个配置文件通常位于 Nginx 的安装目录下的 conf 子目录中。Nginx的基本功能配置是由nginx.conf提供。
2.3.1 配置文件分析
-
全局段配置
全局段配置主要包括用户或组的配置、进程数worker_process(默认为1)、Nginx进行运行文件(nginx.pid)存放地址、日志路径(error.log)及级别。
其中,Nginx 支持的常见日志级别有:a) debug:最详细的日志级别,记录非常详细的信息,通常仅在调试期间使用,因为它会产生大量日志数据。 b) info:默认日志级别,记录一般信息,用于生产环境中的基本日志记录。 c) notice:记录一般但重要的信息,通常用于记录一些不寻常但不是错误的事件。 d) warn:记录警告信息,表示可能存在问题但不一定是错误。 e) error:记录错误信息,表示出现了问题,但 Nginx 可以继续运行。 f) crit:记录严重的错误,通常是关键性问题,可能导致服务器崩溃或无法正常运行。 g) alert:记录需要立即采取行动的错误,通知管理员需要紧急处理的情况。 h) emerg:最高级别的日志,表示系统已经无法正常工作,需要立即采取行动来防止系统崩溃。
-
events段配置
其中, worker_connections指定了每个工作进程能够同时处理的最大并发连接数。当达到这个限制时,新的连接将被放在等待队列中,直到有可用的连接槽。适当调整这个值可以根据服务器硬件和负载来优化性能。
除此之外,events段还可以通过use指定 Nginx 的事件驱动模型,用于处理网络连接,例如epoll、select。multi_accept配置项控制是否允许一个连接被一个工作进程多次接受。例如,multi_accept on表示允许一个连接被一个worker进程多次接受。worker_rlimit_nofile配置项限制每个工作进程能够打开的文件描述符的最大数量。 -
http配置请求信息
Nginx的http配置块是用于配置全局HTTP服务器行为的部分,其中包含了关于 HTTP 请求处理的重要信息。其中,包括MIME 类型设置、访问日志设置、错误日志设置、定义HTTP服务器,包括监听端口号、主机名和域名、默认索引文件位置、静态文件缓存位置等内容。
· 主要配置项说明:
3. Nginx代码分析
3.1 核心模块
core文件夹包含了 Nginx 的核心功能的源代码,这些源代码负责处理 HTTP 请求、事件循环、连接管理、内存管理等核心服务器功能。核心模块的功能如下,
3.2 HTTP模块
HTTP 模块用于处理 HTTP 请求和响应。Nginx 支持模块化的 HTTP 功能,包括 HTTP 服务器、反向代理、负载均衡、缓存等。
3.3 事件模块
事件模块用于处理底层网络事件,例如连接的建立和关闭、数据的读取和写入。
3.4 邮件模块
邮件模块允许 Nginx 用作邮件代理服务器,处理 SMTP、POP3、IMAP 等邮件协议。
4. Nginx主要功能
4.1 Nginx负载均衡
原来单个服务器解决不了交互需求,通过增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,就是负载均衡。Nginx将来自客户端的请求均匀地分发到多个后端服务器,以提高应用程序的性能、可用性和可扩展性。Nginx负载均衡的实现方式有,
1.轮询(Round Robin):
Nginx按照后端服务器定义的顺序依次分发请求,确保每个后端服务器都接收到大致相等数量的请求。
2.IP哈希(IP Hash):
使用客户端的IP地址进行哈希计算,将同一客户端的请求始终分发给相同的后端服务器。这对于需要会话保持的应用程序很有用,以确保用户在一次会话中保持与同一后端服务器的连接。
3.最少连接(Least Connections):
Nginx会将请求分发给当前活跃连接数最少的后端服务器,这有助于将负载均衡在后端服务器之间,以最大程度地减轻繁忙服务器的负担。
4.URL哈希(URL Hash):
使用请求的URL进行哈希计算,将相同URL的请求路由到相同的后端服务器。
4.2 Nginx动静分离
Nginx 动静分离架构将动态生成的内容(如应用程序逻辑、数据库查询等)与静态内容(如图像、CSS、JavaScript 文件等)分开处理,以便更有效地处理请求。动静分离可以通过如下两种方式实现:
1) 将静态文件独立成单独的域名,放在独立的服务器上;
2) 将动态跟静态文件混合在一起发布,通过Nginx来分开。
在上面的nginx.conf中,
1.upstream块定义上游服务器组web_servers,其中包含两个服务器:
•server localhost : 8081:运行在本地主机的 8081 端口上。
•server localhost : 8082:运行在本地主机的 8082 端口上。
这个配置允许负载均衡请求到这两个服务器之间。
2.server 块定义Nginx 的 HTTP 服务器配置,监听端口为 80,服务器名称为localhost。
3.set $doc_root /usr/local/var/www:设置变量 $doc_root,存储静态资源的根目录路径。
4.location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$:一个正则表达式匹配的 location 块,处理静态资源请求,例如图片、CSS和JavaScript文件。
•root $doc_root/img:将请求的静态资源文件从$doc_root/img目录中提供。
5.location /:通用的location块,处理所有其他请求,即动态内容请求。
•proxy_pass http://web_servers:将请求代理到上游服务器组 web_servers中的 Tomcat 实例,实现反向代理功能。
•proxy_set_header Host $host:$server_port:设置请求头,将请求的原始主机和端口信息传递给上游服务器。
6.error_page 块定义一组错误页面,包括 500、502、503 和 504 错误。当发生这些错误时,将发生内部跳转到 /50x.html 页面。
•location = /50x.html:处理内部跳转到/50x.html页面的请求。
•root $doc_root:从根目录$doc_root中提供50x.html页面。
4.3 正向代理与反向代理
· 反向代理
在没有Nginx之前,客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作。引入Nginx之后,客户端到目标服务器的所有请求都先经过Nginx,再由其进行分发到具体的服务器处理,处理完成后再返回Nginx,最后由Nginx将最终的响应结果返回给客户端,这是Nginx的负载均衡或反向代理。反向代理服务器可以提高系统的性能、可用性、安全性,并提供更多的灵活性和控制权。
· 反向代理Nginx配置示例:
1.第一部分指定 Nginx 服务器监听的端口号。Nginx 服务器将监听 HTTP 请求,使用默认的 HTTP 端口 80。此外, server_name 指令定义了此虚拟主机的域名或主机名localhost,表示该配置将用于处理访问本地主机的请求。
2.第二部分是 location 块,将匹配所有请求路径 (/)。具体配置如下:
•proxy_pass http://localhost:8081;:proxy_pass 指令将请求代理到另一个服务器。在这里,请求会被代理到 http://localhost:8081,也就是本地主机的 8081 端口。这意味着 Nginx 将充当反向代理,将请求传递给运行在本地的另一个服务器。
•proxy_set_header Host $host:$server_port;:这一行通过 proxy_set_header 指令设置请求头。它将在请求头中添加一个名为 Host 的字段,该字段的值是客户端请求的主机名或 IP 地址和端口号。这有助于保留客户端请求的原始主机信息。
•proxy_set_header X-Forwarded-For $remote_addr;:同样使用 proxy_set_header 指令,将一个名为 X-Forwarded-For 的字段添加到请求头中。该字段的值是客户端的 IP 地址。这是一种常见的做法,用于传递客户端的真实 IP 地址给后端服务器,以便记录日志或其他目的。
•proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;:这一行定义了在与上游服务器通信时,Nginx 应该如何处理不同类型的错误情况。如果上游服务器返回错误、超时或无效的响应头,或者返回 HTTP 状态码 500、502 或 503,则 Nginx 将尝试从可用的上游服务器中选择另一个,并继续代理请求。
· 正向代理
客户端通过Nginx来访问互联网上的其他服务器,称为正向代理,Nginx用作正向代理服务器。正向代理服务器会将客户端的请求转发到目标服务器,并将目标服务器的响应返回给客户端。这种配置有助于隐藏客户端的真实 IP 地址,并提供一些其他有用的功能,如访问控制、缓存和安全性。
4.4 Nginx请求分发
Nginx 请求分发基于其作为反向代理服务器的功能。当客户端发送请求时,Nginx 接收到请求并将其转发到一个或多个后端服务器,然后将后端服务器的响应返回给客户端。以下是 Nginx 请求分发的基本原理:
- 监听端口:Nginx 作为网络服务器,首先会在一个或多个监听端口上侦听来自客户端的请求。这些请求可以是 HTTP 或 HTTPS 请求,通常监听端口 80(HTTP)和 443(HTTPS)。
- 请求到达:当客户端发送请求到 Nginx 的监听端口时,Nginx 接收到这些请求。
- 请求分发:Nginx 使用配置文件中的负载均衡策略将请求分发到一个或多个后端服务器。负载均衡策略可以是轮询、最小连接数、IP hash 等,这些策略有助于均衡请求在后端服务器之间的分布。
- 后端服务器:Nginx 可以代理请求到一个或多个后端服务器,这些服务器通常是应用程序服务器,例如应用服务器集群、数据库服务器或其他服务。Nginx 将请求发送到后端服务器的 IP 地址和端口。
- 等待响应:Nginx 将请求转发给后端服务器后,等待后端服务器的响应。
- 响应返回:一旦后端服务器处理完请求并生成了响应,Nginx 将响应返回给客户端。这可以包括 HTML 页面、静态资源、JSON 数据等,具体取决于请求的性质。
- 缓存:如果配置了缓存,Nginx 可以在响应中缓存一些静态内容,以减少对后端服务器的请求。这提高了性能和响应时间。
- 日志记录:Nginx 可以记录每个请求和响应的详细信息,这对于监控和分析流量以及故障排除非常有用。
- 安全性:Nginx 可以用于保护后端服务器免受一些常见的网络攻击,例如 DDoS 攻击、SQL 注入和 XSS 攻击。
- SSL 终止:如果启用了 SSL/TLS,Nginx 可以终止 SSL 连接并将未加密的请求转发给后端服务器。这有助于减轻后端服务器的负担。