Nginx 作为开源的轻量级的 HTTP 服务器,广泛应用于分布式应用架构中。本文简要介绍了 Nginx 的特点及使用场景、Nginx 的进程模型和请求处理流程,并结合不同场景进行配置,对 Nginx 的架构和实现原理有个初步的了解。
Nginx(engine X)是一个开源的轻量级的 HTTP 服务器,能够提供高性能的 HTTP 和反向代理服务。与传统的 Apache 服务器相比,在性能上 Nginx 占用系统资源更小、支持高并发,访问效率更高;在功能上,Nginx 不仅作为 Web 服务软件,还适用于反向代理、负载均衡等场景;在安装配置上,Nginx 更为简单、灵活。Nginx 因为并发性能和资源占用上的优势,已经广泛用于大中型互联网企业。
代理服务器一般指代 局域网内部的机器通过代理服务发送请求到互联网上的服务器,代理服务器一般作用于客户端。代理服务器是介于客户端和 Web 服务器之间的服务器,客户端首先与代理服务器创建连接,然后根据代理服务器所使用的代理协议,请求对目标服务器创建连接、或则获得目标服务器的指定资源。
正向代理:为了从原始服务器取的内容,客户端向代理发送一个请求并指定目标(Web 服务器),然后代理向 Web 服务器转交请求并将获得的内容返回给客户端,客户端必须要进行一些特别的设置才能使用正向代理。
反向代理:客户端发送请求到代理服务器,由代理服务器转发给相应的 Web 服务器进行处理,最终返回结果给客户端。
使用反向代理的好处是客户端不需要任何配置就可以访问,对外暴露的是代理服务器的地址隐藏了真实服务器的地址,客户端只需要把请求发送给代理服务器,由代理服务器去选择后端的 Web 服务器,获取到数据后再返回给客户端。
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。 负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如 Web 服务器、FTP 服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
简而言之,单个 Web 应用服务器不能承受日益增长的并发量请求,因此需要不断扩展 web 服务器来支撑高并发请求,根据不同的负载均衡策略将请求分配到各个服务器上。Nginx 支持三种不同的负载均衡策略:
动静分离技术是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,将静态文件放在一个单独的 web 服务器上,加快解析速度,降低原来单个服务器的压力。在 Nginx 的配置中,在 server{} 段中加入带正则匹配的 location 来指定匹配项针对 PHP 的动静分离:静态页面交给 Nginx 处理,动态页面交给 PHP-FPM 模块或 Apache 处理。
Nginx 由内核和模块组成,其中内核在设计上非常简洁,完成的工作非常简单,仅仅通过查找配置文件将客户端请求映射到一个 location block,而在这个 location 中所配置的每个指令将会启动不同的模块去完成相应的工作。
Nginx 的模块从结构上分为核心模块、基础模块和第三方模块,其中用户根据自己的需要开发的模块都属于第三方模块:
Nginx http 功能模块 | 模块说明 |
---|---|
ngx_http_core_module | 包括一些核心的 http 参数配置,对应 Nginx 的配置为 HTTP 区块部分 |
ngx_http_access_module | 访问控制模块,用来控制网站用户对 Nginx 的访问 |
ngx_http_gzip_module | 压缩模块,对 Nginx 返回的数据压缩,属于性能优化模块 |
ngx_http_fastcgi_module | FastCGI 模块,和动态应用相关的模块,例如 PHP |
ngx_http_proxy_module | proxy 代理模块 |
ngx_http_upstream_module | 负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查 |
ngx_http_rewrite_module | URL 地址重写模块 |
ngx_http_limit_conn_module | 限制用户并发连接数及请求数模块 |
ngx_http_limit_req_module | 根据定义的 key 限制 Nginx 请求过程的速率 |
ngx_http_log_module | 访问日志模块,以指定的格式记录 Nginx 客户访问日志等信息 |
ngx_http_auth_basic_module | Web 认证模块,设置 Web 用户通过账号、密码访问 Nginx |
ngx_http_ssl_module | ssl 模块,用于加密的 http 连接,如 https |
ngx_http_stub_status_module | 记录 Nginx 基本访问状态信息等的模块 |
Nginx 模块常规的 HTTP 请求和响应的过程如上图所示,Nginx 模块从功能上分为以下三类:
Nginx 本身处理的工作很少,当它接到一个 HTTP 请求时,通过查找配置文件将此次请求映射到一个 location block,而此 location 中所配置的各个指令则会启动不同的模块去完成工作。
Nginx 默认采用多进程工作方式,在 Nginx 启动后,会运行一个 master 进程和多个 worker 进程。
另外在 Nginx 架构中还有 Cache Loader 和 Cache Manager 进程,Cache Loader 进程加载缓存索引文件信息;Cache Manager 进程管理磁盘的缓存大小,超过预定值大小后最小使用的数据将被删除。
Master 进程主要用来管理 worker 进程,具体包括如下 4 个主要功能:
Master 进程接受到命令重启 Nginx 进程(./nginx -s reload
),会按照以下流程:
Worker 工作进程之间是对等的,每个进程处理请求的机会也是一样的。Nginx 采用 异步非阻塞 的方式来处理网络事件,具体流程如下:
accept_mutex
来保证同一时刻只有一个 work 进程在 accept 连接。accept_mutex
,抢到互斥锁的那个进程注册 listenfd 读事件,在读事件里调用 accept 接受该连接。由上可以看出,一个请求完全由 worker 进程处理,并且只在一个 worker 进程中处理。
Nginx 工作进程会监听套接字上的事件(accept_mutex 和 kernel socketsharding),来决定什么时候开始工作。事件是由新的连接初始化的,这些连接会被分配给状态机。
Nginx中有三大类状态机:处理应用层的 HTTP 状态机、处理 TCP/UDP 的 4 层的传输层状态机、处理邮件的 MAIL 状态机。其中,HTTP 状态机最为常见。
在多种流量进入 Nginx 后,Nginx 的三种状态机在 Nginx 解析出请求后,会动用线程池处理调用,将静态资源、反向代理、错误日志等信息分别导向不同的出口,比如 fastcgi 会导向 PHP 处理、html 会导向 nginx 处理,并将处理请求日志记录到本地或远程服务器中。
Nginx 默认使用多进程的工作方式,相比较多线程的方式,有以下好处:
nginx.conf
后,重新生成新的 worker 进程,新的 worker 进程会以新的配置处理请求,而老的 worker 进程,等把以前的请求处理完成以后,kill 掉就可以。异步非阻塞事件是怎么回事?先看一个请求的完整过程,首先请求过来建立连接,然后再接收数据再发送数据,具体到系统层就是 IO 读写事件。当读写事件没有准备好,如果不采用非阻塞的方式,就得阻塞调用,阻塞调用会进入内核等待,导致 CPU 资源被其它进程占用。当并发请求越大时,等待的事件越多,CPU 利用不上去,并发也上不去。因此 Nginx 使用非阻塞的事件模型,系统中事件模型有很多中,比如 select / poll / kqueue / epoll 等,Nginx 采用 epoll 模型。
Epoll 模型基于事件驱动机制,可以监控多个事件是否准备完毕,如果可以,就放入 epoll 队列,这个过程是异步的,worker 进程只需要从 epoll 队列循环处理即可。Epoll 调用过程如下图所示:
(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
... #全局块
events { #events块
...
}
http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN]
{
...
}
}
server
{
...
}
... #http全局块
}
简单配置如下:
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
。
配置如下:
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 机器。所以这台机器压力会最轻。配置如下:
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/
下。
Nginx 作为开源的轻量级的 HTTP 服务器,广泛应用于分布式应用架构中。本文简要介绍了 Nginx 的特点及使用场景、Nginx 的进程模型和请求处理流程,并结合不同场景进行配置,对 Nginx 的架构和实现原理有个初步的了解。
参考资料:
https://www.nginx.com/resources/library/infographic-inside-nginx/
https://blog.csdn.net/hguisu/article/details/8930668
https://blog.csdn.net/khuangliang/article/details/122345060
https://blog.csdn.net/qq_42511550/article/details/125054697