Nginx 详细教程

目录

  1. Nginx 是什么
  2. 安装 Nginx
  3. 基础命令详解
  4. 配置文件结构详解
  5. 配置静态网站(详细步骤)
  6. 反向代理详解
  7. 负载均衡详解
  8. HTTPS 配置详解
  9. 常用优化配置
  10. 常见问题排查

1. Nginx 是什么

Nginx 是一款开源的 Web 服务器软件,同时具备以下几个核心功能:

  • 静态资源服务器:直接把 HTML、CSS、JS、图片等文件返回给浏览器
  • 反向代理服务器:接收用户的请求,把请求转发给后端的应用程序(比如 Java、Node.js、Python 写的程序),再把结果返回给用户
  • 负载均衡器:当有多台服务器运行同一个应用时,把用户请求分配到不同服务器上,分摊压力
  • HTTPS 终结点:处理 SSL/TLS 加密,让网站支持 HTTPS 访问

Nginx 采用事件驱动、异步非阻塞的处理模型,因此在高并发场景下,占用内存和 CPU 资源都比较少,这也是它被广泛用于生产环境的主要原因。


2. 安装 Nginx

2.1 Ubuntu / Debian 系统

1
2
sudo apt update
sudo apt install nginx -y

安装完成后,Nginx 会自动启动。可以用以下命令确认服务状态:

1
sudo systemctl status nginx

如果看到 active (running) 字样,说明服务已经正常运行。

2.2 CentOS / RHEL 系统

1
2
3
4
sudo yum install epel-release -y
sudo yum install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx # 设置开机自动启动

2.3 验证安装

在浏览器中输入服务器的 IP 地址(如果是本机,输入 http://localhost),如果看到一个显示 “Welcome to nginx!” 的默认页面,说明安装成功。

安装完成后,几个重要的目录/文件位置如下:

路径 作用
/etc/nginx/nginx.conf 主配置文件
/etc/nginx/conf.d/ 存放各个站点独立配置文件的目录(Ubuntu/CentOS通用)
/etc/nginx/sites-available/ 存放站点配置文件(Ubuntu/Debian特有)
/etc/nginx/sites-enabled/ 存放已启用的站点配置(通过软链接指向 sites-available)
/var/www/html/ 默认网站文件存放目录
/var/log/nginx/access.log 访问日志
/var/log/nginx/error.log 错误日志

3. 基础命令详解

命令 说明
sudo systemctl start nginx 启动 Nginx 服务
sudo systemctl stop nginx 停止 Nginx 服务
sudo systemctl restart nginx 完全重启服务(会中断当前所有连接)
sudo systemctl reload nginxsudo nginx -s reload 平滑重新加载配置文件(不会中断当前连接,推荐修改配置后使用这个)
sudo nginx -t 测试配置文件语法是否正确,不会真的应用配置
sudo systemctl enable nginx 设置开机自动启动
nginx -v 查看 Nginx 版本号
nginx -V 查看版本号及编译时的参数和模块信息

重要建议:每次修改完配置文件后,务必先执行 sudo nginx -t 检查语法是否正确,确认没有报错之后,再执行 sudo nginx -s reload 让配置生效。如果直接 reload 而配置文件有语法错误,Nginx 会拒绝加载新配置,继续使用旧配置运行(不会导致服务直接崩溃,但新配置不会生效)。


4. 配置文件结构详解

Nginx 的配置文件由若干个”块”(block)嵌套组成,每个块用 {} 包裹。层级关系如下:

1
2
3
4
5
全局块
└── events 块
└── http 块
└── server 块(可以有多个,每个代表一个虚拟主机/网站)
└── location 块(可以有多个,每个对应一类请求路径)

4.1 全局块

位于配置文件最外层,一般设置影响 Nginx 整体运行的参数,例如:

1
2
3
4
user nginx;                  # Nginx 工作进程运行的用户
worker_processes auto; # 工作进程数量,auto 表示自动设置为CPU核心数
error_log /var/log/nginx/error.log warn; # 错误日志路径及记录级别
pid /run/nginx.pid; # 进程ID存放文件

4.2 events 块

用于配置网络连接相关的参数:

1
2
3
events {
worker_connections 1024; # 每个工作进程允许的最大连接数
}

4.3 http 块

这是配置的核心区域,几乎所有关于 Web 服务的配置都写在这里面,包括日志格式、MIME 类型、Gzip 压缩、以及一个或多个 server 块。

1
2
3
4
5
6
7
8
9
10
11
http {
include /etc/nginx/mime.types; # 引入文件类型对照表
default_type application/octet-stream;

sendfile on; # 开启高效文件传输模式
keepalive_timeout 65; # 长连接超时时间(秒)

server {
# 这里配置具体的网站
}
}

4.4 server 块

一个 server 块代表一个虚拟主机,也就是一个独立的网站。可以通过 server_name 区分不同的域名。

1
2
3
4
5
6
7
8
server {
listen 80; # 监听的端口
server_name example.com; # 绑定的域名

location / {
# 具体的处理规则
}
}

4.5 location 块

用于匹配用户请求的 URL 路径,并定义针对该路径的处理方式。

1
2
3
location /images/ {
root /var/www/static;
}

location 支持多种匹配方式:

写法 说明
location / { } 匹配所有请求(默认规则)
location /abc/ { } 匹配以 /abc/ 开头的路径
location = /abc { } 精确匹配 /abc 这一个路径
location ~ \.php$ { } 用正则表达式匹配,区分大小写,这里匹配以 .php 结尾的请求
location ~* \.(jpg|png|gif)$ { } 正则匹配,不区分大小写

5. 配置静态网站(详细步骤)

假设你有一个静态网站,文件存放在服务器的 /var/www/mysite 目录下,域名是 www.mysite.com

步骤 1:创建网站文件目录并放入文件

1
2
sudo mkdir -p /var/www/mysite
sudo chown -R $USER:$USER /var/www/mysite

将你的 HTML/CSS/JS 文件上传到这个目录,确保目录下有一个 index.html 作为首页。

步骤 2:创建站点配置文件

1
sudo nano /etc/nginx/conf.d/mysite.conf

写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name www.mysite.com mysite.com;

root /var/www/mysite;
index index.html index.htm;

location / {
try_files $uri $uri/ =404;
}

# 单独处理静态资源(可选,便于后续做缓存优化)
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg)$ {
expires 7d;
}
}

各指令说明:

  • listen 80;:监听 80 端口,即普通 HTTP 请求
  • server_name:填写该网站对应的域名,可以填多个,用空格分隔
  • root:指定网站文件的根目录
  • index:指定默认首页文件,按顺序查找,找到第一个存在的文件就返回
  • try_files $uri $uri/ =404;:依次尝试匹配请求的文件,如果都找不到就返回 404 错误

步骤 3:检查语法并使配置生效

1
2
sudo nginx -t
sudo nginx -s reload

步骤 4:配置域名解析

需要在域名服务商的后台,将域名的 A 记录指向服务器的公网 IP 地址,解析生效后即可通过域名访问。


6. 反向代理详解

6.1 使用场景

当你的应用程序(比如用 Node.js、Java Spring Boot、Python Django/Flask 等编写的后端服务)运行在服务器的某个端口上(例如 3000 端口)时,直接对外开放该端口通常不是好的做法,原因包括:

  • 用户访问时需要带上端口号,不美观也不方便记忆
  • 无法直接在该端口上配置 HTTPS(通常做法是让 Nginx 统一处理 HTTPS,再转发到后端的 HTTP 端口)
  • 无法方便地做负载均衡、限流、缓存等操作
  • 后端服务直接暴露在公网,存在一定安全风险

因此常见做法是:让 Nginx 监听 80/443 端口对外提供服务,再由 Nginx 将请求转发给内部运行的后端服务。这种”代理服务器代表后端接收请求”的方式称为反向代理。

6.2 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name api.mysite.com;

location / {
proxy_pass http://127.0.0.1:3000;

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;
}
}

6.3 关键指令详解

指令 详细说明
proxy_pass http://127.0.0.1:3000; 将请求转发到指定地址。地址可以是 IP+端口,也可以是 upstream 定义的服务器组名
proxy_set_header Host $host; 默认情况下,Nginx 转发请求时会用后端地址替换掉 Host 头,导致后端程序拿到的域名不对。加上这行,可以把用户原始请求的域名传递给后端
proxy_set_header X-Real-IP $remote_addr; 将用户的真实 IP 地址通过自定义请求头传给后端。因为经过 Nginx 转发后,后端程序默认只能看到 Nginx 服务器的 IP,而不是用户的真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 记录请求经过的所有代理服务器的 IP 链路,是行业通用的标准做法
proxy_set_header X-Forwarded-Proto $scheme; 告诉后端,用户原始请求使用的是 HTTP 还是 HTTPS 协议

6.4 常用附加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
location / {
proxy_pass http://127.0.0.1:3000;

# 设置超时时间
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;

# 如果后端是 WebSocket 服务,需要加上以下两行
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

7. 负载均衡详解

7.1 使用场景

当单台服务器无法承受全部访问流量时,通常会部署多台运行相同应用的服务器,再通过 Nginx 将请求分发到这些服务器上,这样可以提高整体处理能力,同时当某一台服务器出现故障时,其他服务器还能继续提供服务。

7.2 基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backend {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
server 192.168.1.103:8080;
}

server {
listen 80;
server_name mysite.com;

location / {
proxy_pass http://backend;
}
}

upstream 块用于定义一组服务器,并起一个名字(这里是 backend),之后在 proxy_pass 中直接引用这个名字即可。

7.3 负载均衡策略详解

(1)轮询(默认策略)

不需要额外配置,请求会按顺序依次分配给列表中的每台服务器。

1
2
3
4
upstream backend {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}

(2)加权轮询

适用于服务器性能不一致的情况,权重越高,分配到的请求越多。

1
2
3
4
upstream backend {
server 192.168.1.101:8080 weight=3; # 大约获得 3/4 的请求
server 192.168.1.102:8080 weight=1; # 大约获得 1/4 的请求
}

(3)ip_hash(会话保持)

根据客户端 IP 计算哈希值,保证同一个客户端的请求始终转发到同一台服务器,常用于需要保持会话状态(session)的场景。

1
2
3
4
5
upstream backend {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}

(4)least_conn(最少连接数优先)

将请求分配给当前连接数最少的服务器,适合处理时长差异较大的场景。

1
2
3
4
5
upstream backend {
least_conn;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}

7.4 服务器健康检查相关参数

1
2
3
4
upstream backend {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 backup; # 标记为备用服务器,只有其他服务器都不可用时才启用
}
  • max_fails=3:允许失败的最大次数
  • fail_timeout=30s:失败后,在多长时间内不再向该服务器转发请求
  • backup:标记为备份服务器

8. HTTPS 配置详解

8.1 手动配置(已有证书文件的情况)

假设已经获得证书文件 example.com.crt 和私钥文件 example.com.key:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 443 ssl;
server_name example.com;

ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

location / {
root /var/www/example.com;
index index.html;
}
}

# 将所有 HTTP 请求强制跳转到 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}

8.2 使用 Certbot 自动申请免费证书(推荐)

Certbot 是 Let’s Encrypt 官方推荐的证书申请工具,可以自动申请证书、自动修改 Nginx 配置,并自动设置续期。

步骤 1:安装 Certbot

1
sudo apt install certbot python3-certbot-nginx -y

步骤 2:申请证书并自动配置

1
sudo certbot --nginx -d example.com -d www.example.com

执行后,Certbot 会:

  1. 验证你对该域名的所有权(需要域名已解析到当前服务器)
  2. 自动生成证书文件
  3. 自动修改对应的 Nginx 配置文件,加入 SSL 相关配置
  4. 自动创建一个定时任务,在证书到期前自动续期(证书有效期为 90 天)

步骤 3:手动测试续期是否正常

1
sudo certbot renew --dry-run

如果没有报错,说明自动续期机制配置正常。


9. 常用优化配置

9.1 开启 Gzip 压缩(减少传输数据量)

1
2
3
4
5
6
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1024; # 大于1KB的文件才压缩
gzip_comp_level 6; # 压缩级别,1-9,数字越大压缩率越高但越耗CPU
}

9.2 静态资源浏览器缓存

1
2
3
4
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}

expires 30d; 表示告诉浏览器,这些资源可以缓存 30 天,期间不需要重新向服务器请求,可以显著减少服务器压力,加快页面加载速度。

9.3 隐藏 Nginx 版本号(安全考虑)

1
2
3
http {
server_tokens off;
}

开启后,响应头中不再显示具体的 Nginx 版本号,可以减少被针对性攻击的风险。

9.4 限制请求速率(防止恶意刷接口)

1
2
3
4
5
6
7
8
9
10
http {
# 定义一个限流区域,10m表示用10MB内存记录IP,rate=10r/s表示每个IP每秒最多10个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

server {
location /login {
limit_req zone=mylimit burst=20 nodelay;
}
}
}
  • burst=20:允许瞬时超出速率限制的请求数量,这些请求会被放入队列排队处理
  • nodelay:队列中的请求立即处理,而不是刻意延迟处理

9.5 禁止访问隐藏文件(如 .git、.env 等)

1
2
3
location ~ /\. {
deny all;
}

10. 常见问题排查

现象 常见原因 排查方法
502 Bad Gateway 后端服务未启动;proxy_pass 地址或端口填写错误;后端服务响应超时 检查后端进程是否在运行(如 `ps aux
504 Gateway Timeout 后端处理时间过长,超过了 Nginx 设置的超时时间 适当调大 proxy_read_timeout 等超时参数,同时排查后端程序是否有性能问题
修改配置后不生效 忘记重载,或配置文件路径不对,没有被主配置文件 include 进去 执行 sudo nginx -t 检查是否报错;确认配置文件被正确加载;执行 sudo nginx -s reload
403 Forbidden 文件/目录权限不足;root 路径配置错误;目录下没有 index 指定的文件且没开启目录浏览 检查文件权限(ls -l);确认 Nginx 运行用户对该目录有读取权限;检查 root 路径是否正确
404 Not Found 文件路径写错;location 匹配规则有误 确认文件是否真实存在于 root 对应目录下;检查 URL 路径与 location 规则是否匹配
无法访问,浏览器提示连接被拒绝 Nginx 未启动;防火墙未开放对应端口 执行 sudo systemctl status nginx 确认服务状态;检查防火墙规则(如 ufw statusfirewall-cmd --list-all)

查看日志排查问题

访问日志会记录所有请求的信息:

1
sudo tail -f /var/log/nginx/access.log

错误日志会记录具体的报错原因,是排查问题时最重要的信息来源:

1
sudo tail -f /var/log/nginx/error.log

绝大多数问题,通过查看错误日志里的具体报错信息,都能快速定位到原因所在。


附录:常用配置指令速查表

指令 说明
listen 指定监听的端口
server_name 指定该 server 块对应的域名
root 指定网站文件的根目录
index 指定默认首页文件
location 定义路径匹配规则及处理方式
proxy_pass 将请求转发到指定的地址
upstream 定义一组后端服务器,用于负载均衡
return 直接返回指定的状态码或进行重定向
rewrite 对 URL 进行重写
try_files 按顺序尝试查找文件,都找不到则执行最后的指令
expires 设置资源的浏览器缓存时间
gzip 是否开启 Gzip 压缩
ssl_certificate 指定 SSL 证书文件路径
ssl_certificate_key 指定 SSL 私钥文件路径

如需了解更多细节,可以查阅 Nginx 官方文档