Nginx
Nginx 是一款轻量级的高性能 Web 服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。
核心功能
- 反向代理:接收客户端请求,并将请求转发到后端的服务器上。
- 负载均衡:将客户端请求均衡地分发到多个后端服务器上,提高系统的可用性和性能。
- 动静分离:把静态资源(如图片、CSS、JavaScript 文件等)与动态资源(如 PHP、Python 脚本等)分开处理,提高资源访问效率。
- 缓存:对经常访问的内容进行缓存,减少服务器的负载和响应时间。
安装
1)搭建gcc环境
yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
2)将 nginx-1.20.2.tar.gz 上传到 Linux /opt 目录
3)切换到/opt 目录, 解压 nginx-1.20.2.tar.gz
tar -zxvf nginx-1.20.2.t
4)将解压后的文件放到指定位置
mv nginx-1.20.2 /usr/local/nginx
5)进入文件目录
cd /usr/local/nginx
6)配置 nginx 路径
./configure --prefix=/usr/local/nginx --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock
--error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_gzip_static_module
--http-client-body-temp-path=/var/temp/nginx/client --http-proxy-temp-path=/var/temp/nginx/proxy
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi --http-uwsgi-temp-path=/var/temp/nginx/uwsgi --http-scgi-temp-path=/var/temp/nginx/scgi --conf-path=/usr/local/nginx/nginx.conf
7)补全 nginx 配置目录
mkdir /var/temp/nginx -p
8)编译并安装
make && make install
9)测试配置与 nginx 是否正常,当出现 successful 即可
./sbin/nginx -t
10)启动 nginx
./sbin/nginx -c nginx.conf
11)查看进程/或端口(默认端口是 80)
ps -ef | grep nginx
命令行参数
1)启动 /usr/local/nginx/sbin/nginx -c nginx.conf
2)停止 /usr/local/nginx/sbin/nginx -s stop
3)重新加载(不需要重启) /usr/local/nginx/sbin/nginx -s reload
4)查看版本 /usr/local/nginx/sbin/nginx -v
5)查看版本、配置参数 /usr/local/nginx/sbin/nginx -V
配置文件
Nginx 的主要配置文件通常为 /etc/nginx/nginx.conf
。
配置文件的结构包括:
http
块:包含与 HTTP 相关的配置。server
块:定义虚拟服务器的配置。location
块:用于匹配请求的 URI 并指定相应的处理方式。
Location 实例
Nginx 的 location 匹配规则用于确定如何处理客户端发送的请求。location 后的部分可以使用不同的修饰符或不使用修饰符,具有不同的匹配方式和优先级
location / {
# 处理根路径的请求
}
location /images/ {
# 处理 /images/ 路径下的请求
}
location ~ \.php$ {
# 处理以.php 结尾的请求
}
规则语法:location (=|~|~*|^~) /uri/ { … }
=
:精确匹配。用于不含正则表达式的 URL 前,要求字符串与 URL 严格匹配,完全相等时才能停止向下搜索并处理请求。^~
:用于不含正则表达式的 URL 前,要求 Nginx 服务器找到表示 URL 和字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再进行正则匹配。~
:区分大小写的正则匹配。用于表示 URL 包含正则表达式。~*
:不区分大小写的正则匹配。与~
类似,但不区分字母的大小写。- 无任何前缀:也表示前缀匹配,但是在正则匹配之后。按照最大前缀匹配规则,先匹配普通规则(空、^~);若最终匹配到
^~
,则使用;若匹配到空或未匹配到,则转下一步骤(当前匹配结果暂时保存)。 /
:通用匹配。任何未匹配到其他 location 的请求都会匹配到,相当于 switch 中的 default。
匹配顺序:
- 首先进行精确匹配(
=
),如果匹配成功,则停止其他匹配。 - 然后进行普通字符串匹配(
^~
、无任何前缀),顺序是从长到短。匹配成功的 location 如果使用^~
,则停止其他匹配(正则匹配)。 - 接着进行正则表达式匹配(
~
、~*
),按照配置文件中的物理顺序匹配,只要匹配到一条正则,就不再考虑后面的。 - 如果正则匹配全部失败,则使用普通匹配中保存的结果。
location 分类:
只有两类:正则 location 和普通 location。
- 正则 location:
~
和~*
为正则 location。 - 普通 location:
=
、^~
、@
(用作服务端内部的一种转发行为,很少用)和无任何前缀的都属于普通 location。
一些注意点:
- 匹配的顺序是先匹配普通字符串,然后再匹配正则表达式。普通字符串匹配顺序根据配置中字符长度从长到短,与普通字符串配置的 location 顺序无关,Nginx 会根据配置的长短来进行匹配,但需要注意正则表达式按照配置文件里的顺序测试,找到第一个匹配的正则表达式将停止搜索。
^~
为普通字符匹配,=
为精确匹配,它们除了自身的匹配作用外,还可以阻止 Nginx 继续匹配正则。区别在于^~
依然遵循最大前缀匹配规则,而=
是严格匹配。- 扩展
location / {}
和location =/ {}
的区别:/ {}
作为普通匹配,遵循最大前缀匹配原则;=/ {}
遵循严格匹配规则,只能匹配到http://ip:port/
,同时会停止搜索正则匹配。
负载均衡配置
Nginx 负载均衡可以将客户端的请求分发到多个后端服务器上,以提高系统的性能、吞吐量和可用性。
负载均衡策略:
1)轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。这是默认的负载均衡策略,无需额外配置参数。例如:
upstream myserver {
server 192.168.146:8080;
server 192.168.146:8081;
}
2)权重(weight):通过为每个服务器设置权重,指定轮询几率。权重越高,被分配的客户端越多。权重的默认值为 1,可根据服务器性能或其他因素调整权重。例如,以下配置中,8080 端口的服务器权重为 10,8081 端口的服务器权重为 20,那么大约每 3 次请求中,会有 2 次分发到 8080 端口的服务器,1 次分发到 8081 端口的服务器:
upstream myserver {
server 192.168.146:8080 weight=10;
server 192.168.146:8081 weight=20;
}
3)IP 哈希(ip_hash):根据客户端 IP 地址进行哈希,每个访问客户端会固定访问一个后端服务器,这样可以解决 session 问题。配置如下:
upstream myserver {
ip_hash;
server 192.168.146:8080;
server 192.168.146:8081;
}
4)最少连接数(least_conn):将请求转发到连接数最少的服务器上。这种方式适合服务器性能差异不大的情况,可以使服务器的负载更加均衡。配置如下:
upstream myserver {
least_conn;
server 192.168.146:8080;
server 192.168.146:8081;
}
相关参数:
down
:标识服务器暂时不支持资源请求。例如:server 127.0.0.1:7001 down;
表示该服务器不参与负载。weight
:集群中服务器的权重值,默认是 1。在只有 weight 这一个影响条件下,且集群中服务器都正常,Nginx 会将更多的请求转发到 weight 更大的服务器。max_fails
:允许服务器处理请求时出错的次数,默认为 1。当服务器处理请求发生错误的次数超过 max_fails 时,后续的请求暂时不会转发到这台发生错误的服务器。fail_timeout
:如果某个服务器处理请求时发生错误的次数超过 max_fails,Nginx 将暂时禁止将请求转发到该服务器。当过去 fail_timeout 设置的时间以后,Nginx 会尝试将请求转发到刚才被禁止的服务器,如果服务器正常,那么后续的请求可以继续转发到这台服务器,如果服务器错误,那么继续等待 fail_timeout 时间后再来检测。fail_timeout 默认时间是 10 秒。例如:server 127.0.0.1:7001 max_fail=1 fail_timeout=10s;
backup
:备用服务器,当所有非 backup 服务器发生错误被停用或者设置为 down 时,Nginx 会启用标识为 backup 的服务器。
配置负载均衡的基本步骤如下:
- 在 Nginx 配置文件(通常是
nginx.conf
)的http
模块内,定义一个upstream
块,指定后端服务器列表和相关参数(如上述策略和参数)。 - 在
server
块中,通过location
指令匹配请求,并使用proxy_pass
指令将请求转发到定义的upstream
块。
例如,以下是一个简单的负载均衡配置示例:
http {
upstream myserver {
server 192.168.146:8080;
server 192.168.146:8081;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://myserver;
}
}
}
在上述示例中,定义了一个名为 myserver
的 upstream
块,包含了两个后端服务器 192.168.146:8080
和 192.168.146:8081
。然后,在 server
块中,监听 80 端口,当访问 example.com
时,将请求通过 proxy_pass
转发到 myserver
定义的服务器列表进行负载均衡处理。
动静分离应用
动静分离的好处包括:加快网站的解析速度,减轻后端服务器的压力,使动态页面和静态页面可以由不同的服务器来处理,从而提高请求的访问效率,降低单个服务器的负载。
同时,对于静态资源,可以设置浏览器缓存过期时间,减少与服务器之间的请求流量,提升用户体验。对于经常变动的资源,不建议使用浏览器缓存;而对于不经常变动的资源,通过设置合适的缓存时间,可以避免不必要的请求和流量消耗。
Nginx 动静分离配置的步骤:
1)准备工作:在服务器上创建存放静态资源的目录,并在相应目录中放入静态文件,如图片、html 文件等。
2)配置 Nginx:打开 Nginx 配置文件(通常是nginx.conf
),在server
块中添加相应的location
块来处理静态资源请求。例如:
server {
listen 80;
server_name example.com;
# 处理静态 html 文件请求
location /www/ {
root /data/;
index index.html index.htm;
}
# 处理静态图片文件请求
location /image/ {
root /data/;
autoindex on;
}
}
在上述配置中,/www/
和/image/
是匹配的请求路径。root
指令指定了静态资源的实际存放路径,Nginx 会根据请求路径在该目录下查找对应的文件。autoindex on
表示启用目录索引,当访问/image/
目录时,会列出该目录下的所有文件。
3)重启 Nginx:使配置生效。
通过上述配置,当客户端发送以/www/
开头的请求时,Nginx 会从/data/www/
目录下查找并返回相应的 html 文件;当发送以/image/
开头的请求时,会从/data/image/
目录下查找并返回图片文件或列出目录内容。
工作机制和参数设置
Nginx 是一个高性能的 Web 服务器和反向代理服务器,其工作机制基于异步非阻塞的事件处理模型和多进程架构。
异步非阻塞与 I/O 多路复用:
I/O 多路复用是一种高效处理多个 I/O 流的技术。Nginx 采用的异步非阻塞事件处理机制,可以在一个线程里交替并发地处理多个请求,从而实现高并发和高吞吐。
例如,在处理多个网络连接时,Nginx 并不需要为每个连接创建一个单独的线程或进程去阻塞等待数据。而是通过 I/O 多路复用机制(如 epoll、kqueue 等),一个线程就可以同时监听多个连接的事件。当某个连接有数据到达时,Nginx 能够快速响应并进行处理,处理完后再继续监听其他连接的事件。这种方式避免了大量线程或进程的创建和上下文切换带来的开销,提高了服务器的性能和资源利用率。
多进程架构:
Nginx 在启动后,会有一个 Master 进程和多个 Worker 进程。
-
Master 进程的主要职责是初始化 Nginx 和相关模块、fork Worker 进程、接收并处理外界信号等。例如,它会解析配置文件,调用各个配置指令的回调函数完成模块配置和关联,建立监听套接字(listenfd)等准备工作。之后,它会 fork 出 Worker 子进程和可能的 cache 子进程。
-
Worker 进程负责具体的请求处理工作。当有新的请求到来时,所有 Worker 进程的监听套接字都会变得可读。为了保证只有一个进程处理该连接,Worker 进程在注册监听套接字读事件前要先争抢互斥锁(Accept_mutex)。抢到互斥锁的 Worker 进程注册读事件,在事件中调用 accept 接受连接,然后读取请求、解析请求、处理请求、产生数据并返回给客户端,最后断开连接。一个 HTTP 请求完全由一个 Worker 进程处理,不会在多个 Worker 进程间切换。
这种多进程架构的优势包括:
- 对于每个 Worker 进程来说,由于是独立的进程,不需要加锁,节约了锁导致的资源开销。
- Worker 进程之间互不干扰,例如在平滑重启时,其他未抢到请求的 Worker 进程进行热加载自身以满足最新配置,而抢到请求的 Worker 进程可先处理完当前请求再进行热加载,服务不会中断。
- 采用独立的进程,可以避免一个进程出现问题影响其他进程,一个进程退出后,其他进程仍在工作,服务不会中断,Master 进程也能快速启动新的 Worker 进程。
在 Worker 进程数量设置方面,一般建议将 Worker 数量设置为与服务器 CPU 核心数相等。因为 Nginx 采用了 I/O 多路复用机制,每个 Worker 进程是一个独立的进程且只有一个主线程,通过异步非阻塞的方式处理请求,能将一个 CPU 的性能发挥到极致。设置过少会浪费 CPU 资源,设置过多则会造成 CPU 频繁切换上下文带来的损耗。
搭建高可用集群
我们可以基于 Keepalived 实现 Nginx 高可用集群:
环境准备:
至少需要两台服务器,分别称为主服务器(Master)和备服务器(Backup),并且在这两台服务器上都安装好 Nginx 和 Keepalived 。
配置 Nginx:
在主服务器和备服务器上分别安装和配置 Nginx,确保 Nginx 能够正常运行和提供服务。
配置 Keepalived:
1)主服务器配置:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100
}
}
virtual_server 192.168.1.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.1.1 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.1.2 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
上述配置中:
state MASTER
:表示为主服务器。priority 100
:优先级,数值越大优先级越高。virtual_ipaddress
:设置虚拟 IP 地址。
2)备服务器配置:
与主服务器配置类似,但需要将 state
改为 BACKUP
,priority
值设置得比主服务器低(例如 50)。
启动服务:
在主服务器和备服务器上分别启动 Keepalived 服务:
sudo systemctl start keepalived
工作原理:
Keepalived 会通过发送心跳包来检测主服务器的状态。当主服务器出现故障(例如 Nginx 服务停止、网络中断等),备服务器在一定时间内未收到主服务器的心跳包,就会自动将自己切换为主服务器,并接管虚拟 IP 地址,从而保证服务的连续性。