Nginx 概述

Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强。

多进程模型

Nginx 采用的是固定数量的多进程模型(见下图),由一个主进程(Master Process)和数量与主机 CPU 核数相同的工作进程协同处理各种事件。 主进程负责监听外部控制信号,通过频道机制将相关信号操作传递给工作进程,多个工作进程间通过共享内存来共享数据和信息。
alt text

编译安装

  1. 从官网下载 nginx 压缩包
  2. 编译tar zxmf nginx-1.17.4.tar.gz
  3. 配置环境变量
1
2
3
4
5
cat >/etc/profile.d/nginx.sh << EOF

PATH=$PATH:/usr/local/nginx/sbin

EOF

核心功能

  1. HTTP 服务器:直接处理静态资源(HTML、CSS、JS、图片等),支持虚拟主机、URL 重写、缓存等。将前端打包后的 dist 目录部署到 Nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
server_name frontend.example.com; # 绑定域名

# 网站根目录(指向前端dist目录)
root /var/www/frontend/dist;
index index.html;

# 处理单页应用(SPA)路由(如Vue/React路由)
location / {
try_files $uri $uri/ /index.html; # 刷新页面时重定向到index.html
}

# 静态资源缓存优化
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 30d; # 缓存30天
add_header Cache-Control "public, max-age=2592000"; # 缓存控制头
}

# 禁止访问隐藏文件(如.gitignore)
location ~ /\. {
deny all;
}
}
  1. 反向代理:接收客户端请求,转发到后端服务(如 Java、Python、Node.js 服务),隐藏后端真实地址。反向代理(前后端分离架构)
    前端项目(localhost:80)通过/api 前缀调用后端 API(localhost:8080),用 Nginx 代理解决跨域
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
26
server {
listen 80;
server_name localhost;

# 前端静态资源
location / {
root /var/www/frontend;
index index.html;
}

# 反向代理API请求
location /api/ {
# 代理到后端服务(注意:若proxy_pass末尾带/,则会去掉location的/api/前缀)
proxy_pass http://localhost:8080/; # 例:/api/user → 代理到http://localhost:8080/user

# 传递客户端真实IP和Host(后端可通过X-Real-IP获取客户端IP)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 超时设置
proxy_connect_timeout 30s; # 连接后端超时
proxy_read_timeout 60s; # 读取后端响应超时
}
}
  1. 负载均衡:将请求分发到多个后端节点,实现流量分摊,提高系统可用性。将请求分发到 3 个后端服务(192.168.1.10:8080、192.168.1.11:8080、192.168.1.12:8080)
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
http {
# 定义上游服务器组(后端服务集群)
upstream backend_servers {
# 负载均衡策略(默认轮询)
server 192.168.1.10:8080 weight=3; # weight=3:权重3(接收3/6的请求)
server 192.168.1.11:8080; # 权重默认1
server 192.168.1.12:8080 backup; # backup:仅当主服务器全部故障时启用

# 其他策略:
# ip_hash; # 按客户端IP哈希(同一IP固定到同一服务器,解决会话保持)
# least_conn; # 优先分发到连接数少的服务器
}

server {
listen 80;
server_name api.example.com;

# 所有请求代理到上游服务器组
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
  1. SSL/TLS 终止:处理 HTTPS 加密解密,减轻后端服务压力
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
26
server {
listen 443 ssl; # 监听443端口并启用SSL
server_name example.com www.example.com;

# SSL证书路径(替换为实际路径)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# SSL优化配置
ssl_protocols TLSv1.2 TLSv1.3; # 支持的TLS版本(禁用不安全的SSLv3、TLSv1.0/1.1)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # 加密套件
ssl_prefer_server_ciphers on; # 优先使用服务器定义的加密套件
ssl_session_cache shared:SSL:10m; # SSL会话缓存(减少握手开销)
ssl_session_timeout 1d; # 会话超时时间

# 静态资源配置
root /var/www/example;
index index.html;
}

# HTTP自动跳转HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri; # 永久重定向到HTTPS
}
  1. 限流配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
# 定义限流规则(zone=my_limit:10m 表示内存10MB存储IP状态,rate=10r/s 表示每秒10个请求)
limit_req_zone $binary_remote_addr zone=my_limit:10m rate=10r/s;

server {
listen 80;
server_name example.com;

# 对/api路径应用限流
location /api/ {
limit_req zone=my_limit burst=20 nodelay; # burst=20:允许20个突发请求,nodelay:不延迟处理
proxy_pass http://backend;
}
}
}

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 启动Nginx(若未启动)
sudo nginx

# 停止Nginx(强制终止,可能丢失请求)
sudo nginx -s stop

# 优雅停止(处理完当前请求后关闭)
sudo nginx -s quit

# 重载配置文件(无需重启,推荐)
sudo nginx -s reload

# 检查配置文件语法是否正确
sudo nginx -t # 输出"nginx: configuration file /etc/nginx/nginx.conf test is successful"表示正确

# 查看Nginx版本
nginx -v # 简单版本信息
nginx -V # 详细版本+编译参数(如支持的模块)

Nginx 核心配置文件

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 全局块(main):影响Nginx整体的配置
user nginx; # 运行Nginx的用户/组
worker_processes auto; # worker进程数(auto表示与CPU核心数一致)
error_log /var/log/nginx/error.log; # 错误日志路径
pid /run/nginx.pid; # 进程PID文件路径

# 事件块(events):影响Nginx与用户的网络连接
events {
worker_connections 1024; # 单个worker进程最大连接数
use epoll; # 事件驱动模型(Linux推荐epoll,BSD用kqueue)
}

# HTTP块:配置HTTP服务器的核心区块,可包含多个server块(虚拟主机)
http {
include /etc/nginx/mime.types; # 引入MIME类型映射(如.js对应application/javascript)
default_type application/octet-stream; # 默认MIME类型(未知类型时)

# 日志格式定义(main为格式名称,可在server/location中引用)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # 访问日志路径+格式

sendfile on; # 开启高效文件传输模式(零拷贝)
tcp_nopush on; # 配合sendfile使用,提高网络传输效率
tcp_nodelay on; # 禁用Nagle算法,减少延迟(适合实时通信)
keepalive_timeout 65; # 长连接超时时间(秒)
types_hash_max_size 4096; # 类型哈希表大小(影响MIME类型查找效率)

include /etc/nginx/conf.d/*.conf; # 引入子配置文件(通常存放虚拟主机配置)

# 服务器块(server):定义一个虚拟主机(可多个)
server {
listen 80; # 监听端口(默认80)
server_name localhost; # 绑定的域名/IP(可多个,空格分隔)
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页文件

# location块:匹配请求路径,定义该路径的处理规则(可多个)
location / {
# 路径匹配规则:/表示匹配所有未被其他location匹配的请求
try_files $uri $uri/ =404; # 尝试访问请求的文件/目录,不存在则返回404
}

# 错误页面配置
error_page 404 /404.html;
location = /404.html {
internal; # 仅内部跳转访问,禁止直接访问
}
}
}

Nginx 配置文件在 conf 目录下
nginx.conf:Nginx 默认的配置入口文件;
包含 3 部分内容:全局块、events 块、http 块。

  1. 全局块。
    配置文件开始到 events 块开始中间的内容,此处的配置影响 nginx 服务器整体的运行,包括 worker 进程的数量、错误日志的位置等。

  2. events 块:events 块主要是 nginx 服务器与用户的网络连接

1
2
3
4
5
6
events {


#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数,默认为512
}
  1. http 块:包含 HTTP 协议相关的全局配置,如日志格式、MIME 类型、连接超时等,核心是 server 块(虚拟主机)。
  2. server 块(虚拟主机):一个 server 块对应一个虚拟主机(可通过域名或端口区分多个网站),核心指令:
1
2
3
4
listen:监听端口(如80、443 ssl),可指定 IP(如listen 192.168.1.1:80;)。
server_name:匹配客户端请求的 Host 头,支持精确匹配(www.example.com)、通配符(*.example.com)、正则(~^www\d+\.example\.com$)。
root:网站根目录(请求路径会拼接在 root 后,如root /var/www,请求/index.html对应/var/www/index.html)。
index:默认首页文件(多个时按顺序查找)。
  1. location 块:用于匹配请求的 URI(路径),定义该路径的处理规则,核心是匹配规则和处理指令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
server_name example.com;

# 精确匹配首页
location = / {
return 200 "首页";
}

# 前缀匹配静态资源(优先于正则)
location ^~ /static/ {
root /var/www; # 请求/static/css/main.css → /var/www/static/css/main.css
}

# 正则匹配图片(不区分大小写)
location ~* \.(jpg|png|gif)$ {
expires 30d; # 缓存30天
}

# 普通前缀匹配API
location /api {
proxy_pass http://backend:8080; # 反向代理到后端服务
}
}

Nginx 使用哈希表加速对 Nginx 配置中常量的处理,哈希表是通过关键码来快速访问常量对应值的数据存储结构,在通过哈希表获取数据的过程中,其内部实现通过相关函数将常量名转换为一个关键码来实现对应值的快速定位和读取。

Nginx 高級特性

热部署与平滑升级

Nginx 支持不中断服务的情况下升级版本或重载配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 备份旧的nginx二进制文件
sudo cp /usr/sbin/nginx /usr/sbin/nginx.old

# 2. 替换为新版本二进制文件(假设新文件为nginx.new)
sudo cp nginx.new /usr/sbin/nginx

# 3. 向master进程发送USR2信号(启动新master+新worker,旧worker继续处理请求)
sudo kill -USR2 $(cat /run/nginx.pid)

# 4. 向旧master发送WINCH信号(优雅关闭旧worker)
sudo kill -WINCH $(cat /run/nginx.pid.oldbin)

# 5. 确认新服务正常后,关闭旧master
sudo kill -QUIT $(cat /run/nginx.pid.oldbin)

日志管理

Nginx 日志默认按文件存储,可通过 logrotate 工具实现日志轮转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /etc/logrotate.d/nginx 配置示例
/var/log/nginx/*.log {
daily # 每天轮转
missingok # 日志不存在时不报错
rotate 7 # 保留7天日志
compress # 压缩旧日志
delaycompress # 延迟压缩(下一次轮转时压缩当前日志)
notifempty # 空日志不轮转
create 0640 nginx nginx # 新建日志文件的权限和属主
postrotate
# 轮转后向Nginx发送USR1信号,重新打开日志文件
kill -USR1 $(cat /run/nginx.pid 2>/dev/null) 2>/dev/null || true
endscript
}