Nginx从入门到精通
Nginx 详细教程
目录
1. Nginx 是什么
Nginx 是一款开源的 Web 服务器软件,同时具备以下几个核心功能:
- 静态资源服务器:直接把 HTML、CSS、JS、图片等文件返回给浏览器
- 反向代理服务器:接收用户的请求,把请求转发给后端的应用程序(比如 Java、Node.js、Python 写的程序),再把结果返回给用户
- 负载均衡器:当有多台服务器运行同一个应用时,把用户请求分配到不同服务器上,分摊压力
- HTTPS 终结点:处理 SSL/TLS 加密,让网站支持 HTTPS 访问
Nginx 采用事件驱动、异步非阻塞的处理模型,因此在高并发场景下,占用内存和 CPU 资源都比较少,这也是它被广泛用于生产环境的主要原因。
2. 安装 Nginx
2.1 Ubuntu / Debian 系统
1 | sudo apt update |
安装完成后,Nginx 会自动启动。可以用以下命令确认服务状态:
1 | sudo systemctl status nginx |
如果看到 active (running) 字样,说明服务已经正常运行。
2.2 CentOS / RHEL 系统
1 | sudo yum install epel-release -y |
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 nginx 或 sudo 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 | 全局块 |
4.1 全局块
位于配置文件最外层,一般设置影响 Nginx 整体运行的参数,例如:
1 | user nginx; # Nginx 工作进程运行的用户 |
4.2 events 块
用于配置网络连接相关的参数:
1 | events { |
4.3 http 块
这是配置的核心区域,几乎所有关于 Web 服务的配置都写在这里面,包括日志格式、MIME 类型、Gzip 压缩、以及一个或多个 server 块。
1 | http { |
4.4 server 块
一个 server 块代表一个虚拟主机,也就是一个独立的网站。可以通过 server_name 区分不同的域名。
1 | server { |
4.5 location 块
用于匹配用户请求的 URL 路径,并定义针对该路径的处理方式。
1 | location /images/ { |
location 支持多种匹配方式:
| 写法 | 说明 |
|---|---|
location / { } |
匹配所有请求(默认规则) |
location /abc/ { } |
匹配以 /abc/ 开头的路径 |
location = /abc { } |
精确匹配 /abc 这一个路径 |
location ~ \.php$ { } |
用正则表达式匹配,区分大小写,这里匹配以 .php 结尾的请求 |
location ~* \.(jpg|png|gif)$ { } |
正则匹配,不区分大小写 |
5. 配置静态网站(详细步骤)
假设你有一个静态网站,文件存放在服务器的 /var/www/mysite 目录下,域名是 www.mysite.com。
步骤 1:创建网站文件目录并放入文件
1 | sudo mkdir -p /var/www/mysite |
将你的 HTML/CSS/JS 文件上传到这个目录,确保目录下有一个 index.html 作为首页。
步骤 2:创建站点配置文件
1 | sudo nano /etc/nginx/conf.d/mysite.conf |
写入以下内容:
1 | server { |
各指令说明:
listen 80;:监听 80 端口,即普通 HTTP 请求server_name:填写该网站对应的域名,可以填多个,用空格分隔root:指定网站文件的根目录index:指定默认首页文件,按顺序查找,找到第一个存在的文件就返回try_files $uri $uri/ =404;:依次尝试匹配请求的文件,如果都找不到就返回 404 错误
步骤 3:检查语法并使配置生效
1 | sudo nginx -t |
步骤 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 | server { |
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 | location / { |
7. 负载均衡详解
7.1 使用场景
当单台服务器无法承受全部访问流量时,通常会部署多台运行相同应用的服务器,再通过 Nginx 将请求分发到这些服务器上,这样可以提高整体处理能力,同时当某一台服务器出现故障时,其他服务器还能继续提供服务。
7.2 基本配置
1 | upstream backend { |
upstream 块用于定义一组服务器,并起一个名字(这里是 backend),之后在 proxy_pass 中直接引用这个名字即可。
7.3 负载均衡策略详解
(1)轮询(默认策略)
不需要额外配置,请求会按顺序依次分配给列表中的每台服务器。
1 | upstream backend { |
(2)加权轮询
适用于服务器性能不一致的情况,权重越高,分配到的请求越多。
1 | upstream backend { |
(3)ip_hash(会话保持)
根据客户端 IP 计算哈希值,保证同一个客户端的请求始终转发到同一台服务器,常用于需要保持会话状态(session)的场景。
1 | upstream backend { |
(4)least_conn(最少连接数优先)
将请求分配给当前连接数最少的服务器,适合处理时长差异较大的场景。
1 | upstream backend { |
7.4 服务器健康检查相关参数
1 | upstream backend { |
max_fails=3:允许失败的最大次数fail_timeout=30s:失败后,在多长时间内不再向该服务器转发请求backup:标记为备份服务器
8. HTTPS 配置详解
8.1 手动配置(已有证书文件的情况)
假设已经获得证书文件 example.com.crt 和私钥文件 example.com.key:
1 | server { |
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 会:
- 验证你对该域名的所有权(需要域名已解析到当前服务器)
- 自动生成证书文件
- 自动修改对应的 Nginx 配置文件,加入 SSL 相关配置
- 自动创建一个定时任务,在证书到期前自动续期(证书有效期为 90 天)
步骤 3:手动测试续期是否正常
1 | sudo certbot renew --dry-run |
如果没有报错,说明自动续期机制配置正常。
9. 常用优化配置
9.1 开启 Gzip 压缩(减少传输数据量)
1 | http { |
9.2 静态资源浏览器缓存
1 | location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ { |
expires 30d; 表示告诉浏览器,这些资源可以缓存 30 天,期间不需要重新向服务器请求,可以显著减少服务器压力,加快页面加载速度。
9.3 隐藏 Nginx 版本号(安全考虑)
1 | http { |
开启后,响应头中不再显示具体的 Nginx 版本号,可以减少被针对性攻击的风险。
9.4 限制请求速率(防止恶意刷接口)
1 | http { |
burst=20:允许瞬时超出速率限制的请求数量,这些请求会被放入队列排队处理nodelay:队列中的请求立即处理,而不是刻意延迟处理
9.5 禁止访问隐藏文件(如 .git、.env 等)
1 | location ~ /\. { |
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 status 或 firewall-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 官方文档。