NGINX介绍
Nginx(Engine X) 是一个高性能的开源 HTTP 和反向代理服务器,同时也可以作为 负载均衡器、邮件代理服务器(IMAP/POP3/SMTP) 使用。
编译安装NGINX
编译安装需要下载nginx开源的代码进行自编译和安装,所以需要有编译环境。
1 | 安装编译器和 make 实用程序 |
准备pcre编译环境
目前的nginx不自带PCRE代码,所以经常会在make时报错,需要先准备pcre的源码,参与make,并在./configure 的--with-pcre=../pcre2-10.39显式指定pcre源码路径。
1 | cd /opt/nginx |
准备zlib编译环境
目前的nginx不自带ZLIB代码,所以经常会在make时报错,需要先准备ZLIB的源码,参与make,并在./configure 的--with-zlib=../zlib-1.3.1显式指定ZLIB源码路径。
1 | cd /opt/nginx |
安装nginx开源代码(1.29.1版本)
1 | wget https://github.com/nginx/nginx/releases/download/release-1.29.1/nginx-1.29.1.tar.gz |
配置参数(点击这里查看详细参数列表)
1 | ./configure \ |
编译及编译安装
1 | make |
测试是否正常完成编码安装
1 | 是否在/usr/lib/nging/nginx有生成 |
NGINX使用命令
nginx 拥有一个主进程和几个工作进程。主进程的主要目的是读取和评估配置,并维护工作进程。工作进程负责实际处理请求。nginx 采用事件驱动模型和依赖于操作系统的机制,以有效地在工作进程之间分发请求。工作进程的数量在配置文件中定义,可以固定为给定配置或根据可用 CPU 内核数量自动调整
nginx 及其模块的工作方式由配置文件决定。默认情况下,配置文件名为 nginx.conf,位于目录 /usr/local/nginx/conf、/etc/nginx 或 /usr/local/etc/nginx 中。默认情况是/usr/local/nginx/conf,若要自定义需要在配置参数时填写--prefix=*path*。
要启动 nginx,请运行可执行文件。nginx 启动后,可以通过调用可执行文件并带上 -s 参数来控制。请使用以下语法:
1 nginx -s signal
其中 signal 可以是以下之一:
singal
1
2
3
4 stop — 快速关闭
quit — 优雅关闭(等待工作进程完成处理当前请求后停止nginx进程)
reload — 重新加载配置文件
reopen — 重新打开日志文件
配置文件中所做的更改在发送重新加载配置命令给 nginx 或重启 nginx 之前不会生效。要重新加载配置,请执行:
1 nginx -s reload
一旦主进程收到重新加载配置的信号,它会检查新配置文件的语法有效性并尝试应用其中提供的配置。如果成功,主进程将启动新的工作进程,并向旧的工作进程发送消息,请求它们关闭。否则,主进程将回滚更改,并继续使用旧配置。旧的工作进程收到关闭命令后,将停止接受新连接,并继续处理当前请求,直到所有此类请求都得到处理。之后,旧的工作进程退出。
也可以借助 Unix 工具(例如 kill 工具)向 nginx 进程发送信号。在这种情况下,信号直接发送到具有给定进程 ID 的进程。默认情况下,nginx 主进程的进程 ID 写入 /usr/local/nginx/logs 或 /var/run 目录下的 nginx.pid 文件中。例如,如果主进程 ID 为 1628,要发送导致 nginx 优雅关闭的 QUIT 信号,请执行:
1 kill -s QUIT 1628
要获取所有正在运行的 nginx 进程列表,可以使用 ps 工具,例如,以下方式:
1 ps -ax | grep nginx
NGINX配置文件
提供静态内容
目标:
让 Nginx 直接返回本地文件(如 HTML、图片等)。
步骤:
创建文件目录:
1
2mkdir -p /data/www /data/images
echo "Hello Nginx" > /data/www/index.html编辑配置文件(通常是
/usr/local/nginx/conf/nginx.conf或/etc/nginx/nginx.conf):1
2
3
4
5
6
7
8
9
10
11http {
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
}启动或重载配置:
1
nginx -s reload
效果:
- 访问
/images/example.png→ 读取/data/images/example.png - 访问
/index.html→ 读取/data/www/index.html
配置代理服务器
目标:
让 Nginx 根据请求类型决定:
- 图片等静态资源 → 本地目录读取;
- 其他请求 → 转发到另一个服务器(反向代理)。
步骤:
在同一个 nginx 实例中新增一个被代理服务器(监听 8080):
1
2
3
4
5
6server {
listen 8080;
root /data/up1;
location / { }
}目录
/data/up1用于被代理服务内容。修改原服务器,让它作为“代理服务器”:
1
2
3
4
5
6
7
8
9server {
location / {
proxy_pass http://127.0.0.1:8080;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}重载配置:
1
nginx -s reload
效果:
- 请求
.gif、.jpg、.png→ 从/data/images返回; - 其他请求 → 转发到本地的
8080端口处理。
基于名称的虚拟服务器
server块可以对访问的内容进行处理,若是监听端口相同,将会根据server_name域名来区分访问内容。若是端口和域名都相同,就会有一个被选中,其余不会反馈。
nginx 首先决定哪个 服务器 应该处理请求。让我们从一个简单的配置开始,其中所有三个虚拟服务器都监听端口 *:80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
...
}
server {
listen 80;
server_name example.com www.example.com;
...
}
默认服务器是第一个 — 这是 nginx 的标准默认行为。也可以使用 listen指令中的 default_server 参数明确设置哪个服务器作为默认服务器
1
2
3
4
5 server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
如何阻止处理具有未定义服务器名的请求
如果不允许没有“Host”头部字段的请求,可以定义一个直接丢弃请求的服务器
1
2
3
4
5 server {
listen 80;
server_name "";
return 444;
}
在这里,服务器名被设置为空字符串,这将匹配没有“Host”头部字段的请求,并返回 nginx 特殊的非标准状态码 444,该状态码会关闭连接。
自版本 0.8.48 起,这是服务器名的默认设置,因此可以省略
server_name ""。在早期版本中,机器的 主机名 被用作默认服务器名。
混合使用基于名称和基于 IP 的虚拟服务器
让我们看一个更复杂的配置,其中一些虚拟服务器监听不同的地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
...
}
在此配置中,nginx 首先根据 listen 指令检查 server 块,以匹配请求的 IP 地址和端口。然后,它会根据匹配了 IP 地址和端口的 server 块中的 server_name 条目检查请求的“Host”头部字段。如果找不到服务器名,请求将由默认服务器处理。例如,在 192.168.1.1:80 端口收到的对 www.example.com 的请求,将由 192.168.1.1:80 端口的默认服务器处理,即由第一个服务器处理,因为没有为该端口定义 www.example.com。
如前所述,默认服务器是监听端口的属性,可以为不同的端口定义不同的默认服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
...
}
负载均衡
nginx 支持以下负载均衡机制(或方法):
- round-robin(轮询) — 请求以轮询方式分发到应用服务器,
- least-connected(最少连接) — 下一个请求分配给活动连接数最少的服务器,
- ip-hash(IP 哈希) — 使用哈希函数确定下一个请求应选择哪个服务器(基于客户端的 IP 地址)。
默认负载均衡配置
使用 nginx 进行负载均衡的最简单配置可能如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
在上面的示例中,srv1-srv3 上运行着同一应用程序的 3 个实例。如果未明确配置负载均衡方法,则默认为轮询。所有请求都 代理 到服务器组 myapp1,并且 nginx 应用 HTTP 负载均衡来分发请求。
nginx 中的反向代理实现包括对 HTTP、HTTPS、FastCGI、uwsgi、SCGI、memcached 和 gRPC 的负载均衡。
要配置 HTTPS 负载均衡而不是 HTTP,只需将协议设置为“https”。
配置 FastCGI、uwsgi、SCGI、memcached 或 gRPC 的负载均衡时,请分别使用 fastcgi_pass、uwsgi_pass、scgi_pass、memcached_pass 和 grpc_pass 指令。
最少连接负载均衡
另一种负载均衡策略是最少连接。在某些请求完成时间较长的情况下,最少连接可以更公平地控制应用实例上的负载。
使用最少连接负载均衡,nginx 会尽量避免用过多的请求使繁忙的应用服务器过载,而是将新请求分发到较空闲的服务器。
在服务器组配置中使用 least_conn 指令时,nginx 中的最少连接负载均衡就会激活。
1
2
3
4
5
6 upstream myapp1 {
least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
会话保持
请注意,使用轮询或最少连接负载均衡时,客户端的后续每个请求可能会被分发到不同的服务器。无法保证同一客户端始终会被定向到同一服务器。
如果需要将客户端绑定到特定的应用服务器 — 换句话说,使客户端的会话“粘性”(sticky)或“持久化”(persistent),即始终尝试选择同一服务器 — 则可以使用 ip-hash 负载均衡机制。
使用 ip-hash 时,客户端的 IP 地址用作哈希键,以确定服务器组中应选择哪个服务器来处理客户端的请求。此方法确保来自同一客户端的请求将始终被定向到同一服务器,除非该服务器不可用。
要配置 ip-hash 负载均衡,只需将 ip_hash 指令添加到服务器(upstream)组配置中。
1
2
3
4
5
6 upstream myapp1 {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
加权负载均衡
通过使用服务器权重,还可以进一步影响 nginx 的负载均衡算法。
在上面的示例中,未配置服务器权重,这意味着所有指定的服务器对于特定的负载均衡方法都被视为同等合格。
特别是在轮询方式下,这也意味着请求在服务器之间或多或少地均匀分布 — 前提是有足够的请求,并且请求以统一的方式处理并足够快地完成。
当为服务器指定了 weight 参数时,该权重会作为负载均衡决策的一部分被考虑在内。
1
2
3
4
5 upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
}
使用此配置,每 5 个新请求将按以下方式分发到应用实例:3 个请求将定向到 srv1,1 个请求将发送到 srv2,另一个请求 — 到 srv3。
在 nginx 的最新版本中,同样可以在最少连接和 ip-hash 负载均衡中使用权重。
健康检查
nginx 中的反向代理实现包括带内(或被动)服务器健康检查。如果来自特定服务器的响应失败并带有错误,nginx 会将该服务器标记为失败,并在一段时间内尝试避免选择该服务器处理后续的入站请求。
max_fails 指令设置了在 fail_timeout 期间与服务器通信连续失败的尝试次数。默认情况下,max_fails 设置为 1。当设置为 0 时,该服务器的健康检查将被禁用。fail_timeout 参数还定义了服务器将被标记为失败的时长。在服务器失败后的 fail_timeout 时间间隔后,nginx 将开始使用实际的客户端请求来优雅地探测服务器。如果探测成功,服务器将被标记为正常运行。
配置HTTPS服务器
要配置 HTTPS 服务器,必须在 server 块中,为 监听套接字 启用 ssl 参数,并指定 服务器证书 和 私钥 文件的位置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 例子1
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
例子2
server {
listen 443 ssl;
server_name data2.com;
ssl_certificate /www/server.crt;
ssl_certificate_key /www/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /www/data2;
location / {}
}
服务器证书是一个公共实体。它会发送给每个连接到服务器的客户端。私钥是一个安全实体,应存储在一个访问受限的文件中,但 nginx 的主进程必须可读。私钥也可以存储在与证书相同的文件中。
1
2 ssl_certificate www.example.com.cert;
ssl_certificate_key www.example.com.cert;
在这种情况下,文件访问权限也应受限。尽管证书和私钥存储在同一个文件中,但只有证书会发送给客户端。