文章目录
- Nginx 快速复习指南
- 一、概述
- 1.1 什么是 Nginx
- 1.2 Nginx 架构
- 1.3 Nginx 的增强版
- 二、安装 Nginx 和 添加模块
- 三、配置文件结构
- 3.1 配置文件目录
- 3.2 配置文件结构
- 四、常用功能示例
- 4.1 静态资源服务
- 4.2 动静分离
- 4.3 反向代理
- 4.4 负载均衡
- 4.5 URL 重写
- 4.6 跨域处理(CORS)
- 4.7 防盗链
- 4.8 限流
- 五、生产环境常用配置
- 六、常用指令
Nginx 快速复习指南
适用于有一定基础的开发者快速唤醒记忆,以面试 / 实战为导向。
一、概述
1.1 什么是 Nginx
Nginx(读作 “engine-X”)是一个高性能的HTTP 服务器、反向代理服务器,同时支持 IMAP / POP3 / SMTP 邮件代理。
它的诞生是为了解决C10K 问题(同时处理一万个并发连接)。在传统 Apache 的进程/线程模型下,每个连接消耗大量内存和 CPU 上下文切换开销,而 Nginx 通过事件驱动 + 异步非阻塞 I/O模型,以极低的内存消耗支撑数万并发。
Nginx 的核心功能极简,但可以通过模块化的方式轻松扩展功能。
常用于:
- 静态资源服务:专门托管图片、JS、CSS、HTML、静态页面、安装包等。
- 动静分离:静态资源由 Nginx 直接响应,动态接口转发给后端业务服务。
- 反向代理:客户端请求统一接入,再转发到后端应用。既能简化域名管理,又能隐藏后端真实服务地址与端口,提升内网安全性。
- 负载均衡:把请求分发到后端服务器集群,支持策略:轮询、权重、IP 哈希、最少连接。
- HTTPS 证书代理:统一配置 SSL 证书。
- URL 重写:实现地址跳转、伪静态。
- 流量控制与安全防护:限流、防盗链、IP 黑白名单。
- 跨域处理:在 Nginx 层配置跨域响应头,解决前后端分离的跨域问题。
- 缓存服务:Nginx 本地缓存,对高频接口 / 页面做缓存,减少后端重复查询与计算。
1.2 Nginx 架构
Nginx 采用多进程模型:
- Master 进程:用来处理大部分 Nginx 命令,以及创建 Worker 子进程。
- Worker 进程:由 Master 进程创建,用来真正的处理网络请求。每个 Worker 进程的内部,只有一个线程,实现基于异步非阻塞 IO 实现事件驱动器功能,从而处理网络请求的接入、读取、处理、响应。
因为每个 Worker 中只有一个线程来进行处理,所以当多个请求同一时刻进入相同 Worker 时,请求是串行处理的,虽然 IO 部分确实是 异步非阻塞的(操作系统实现),但是处理部分不是(Nginx 应用实现),所以理论上是会有卡顿的。之所以平时看不出来卡顿,是因为 Nginx 的工作几乎都是转发之类的,所以处理的很快,但这不影响其内部串行处理的事实。
1.3 Nginx 的增强版
不少组织基于原生 Nginx 进行功能增强,衍生出两类主流发行版:
- Tengine:淘宝定制版 Nginx,优化内核,侧重高并发、高可用与负载均衡。
- OpenResty:基于原生 Nginx 扩展,核心能力是支持 Lua 脚本,实现可编程扩展。
二、安装 Nginx 和 添加模块
安装有两种常见方式:
- 包管理器安装:方便,但是不支持添加第三方模块,只支持官方模块。
- 下载源码后编译安装:可以随便添加模块。
更推荐使用源码编译安装的方式,更灵活,添加/删除模块更方便,生产环境常用。
源码编译安装示例
# 1. 下载源码wgethttps://nginx.org/download/nginx-1.26.0.tar.gztar-zxvfnginx-1.26.0.tar.gzcdnginx-1.26.0# 2. 配置(按需增减模块)默认安装路径:/usr/local/nginx./configure--prefix=安装路径 --with-内置模块1 --with-内置模块N --add-module=自定义模块1 --add-module=自定义模块N# 3. 编译安装make&&makeinstall# 4. 验证/usr/local/nginx/sbin/nginx-V# 访问默认页面(看到 "Welcome to nginx" 页面说明安装成功。)curlhttp://127.0.0.1常用模块:
--with-http_ssl_module:HTTPS 支持(必选)--with-http_gzip_static_module:开启预压缩支持,开启后, Nginx 优先查找同名的.gz文件直接发送;找不到.gz文件时,才找源文件并压缩返回。
后期想添加新的模块,指定新模块重新编译安装即可(不要忘记添加旧模块)。
三、配置文件结构
3.1 配置文件目录
/etc/nginx/nginx.conf:主配置文件/etc/nginx/conf.d/*.conf:子配置目录(推荐各个应用的配置单独拆分到这里)/usr/local/nginx/conf/:源码编译安装时的配置目录
3.2 配置文件结构
Nginx 的配置文件按层级组织,内层上下文会继承外层的指令值,如果内层重新指定,则覆盖外层,从外到内依次为:
main(全局上下文) ├── events # 事件模型配置块(必须有) └── http # HTTP 配置块(必须有) ├── server # 虚拟主机配置块(至少一个) │ ├── location # URL 匹配规则(至少一个) │ └── location ├── server │ └── location └── ...各配置块解释和常用指令
- main: 全局配置,影响所有配置块,常用指令有:
- worker_processes: Worker 进程数量,设为 auto 则等于 CPU 核心数,例:
worker_processes auto; - user: Worker 进程运行的用户,例:
user nginx; - error_log: 错误日志路径及级别,例:
error_log logs/error.log warn; - pid: 主进程 PID 文件路径,例:
pid /var/run/nginx.pid;
- worker_processes: Worker 进程数量,设为 auto 则等于 CPU 核心数,例:
- events: 事件驱动相关,常用指令有:
- worker_connections: 每个 Worker 最大连接数,例:
worker_connections 1024; - use: 事件模型,Linux 用 epoll,macOS 用 kqueue,例:
use epoll; - multi_accept: 一次 accept 多个连接,例:
multi_accept on;
- worker_connections: 每个 Worker 最大连接数,例:
- http: HTTP 相关配置,常用指令有:
- include: 引入其他配置文件,例:
include mime.types; - sendfile: 零拷贝传输文件,例:
sendfile on; - keepalive_timeout: 长连接超时秒数,例:
keepalive_timeout 65; - gzip: 响应压缩开关,例:
gzip on; - client_max_body_size: 请求体大小限制,例:
client_max_body_size 10m;
- include: 引入其他配置文件,例:
- server: 配置站点(对外提供访问的入口),常用指令有:
- listen: 监听端口,例:
listen 80;(HTTPS:listen 443 ssl;) - server_name: 域名,支持通配符,例:
server_name example.com; - root: 站点根目录,例:
root /var/www/html;,nginx 会去这个目录找资源。 - index: 默认首页,例:
index index.html index.htm;,nginx 会在根目录中找 index.html,找不到就找 index.htm
- listen: 监听端口,例:
- location: URL 匹配规则,根据路径,执行不同处理逻辑,以下按优先级:
location = /exact:精确匹配location ^~ /static/:前缀优先匹配(不检查正则)location ~ \.php$:正则匹配(~区分大小写,~*不区分)location /api/:前缀匹配location /:匹配根路径
以下是最简可运行配置示例:
events {} # 事件配置(必须有,可为空) http { # HTTP 核心配置 server { # 虚拟主机定义 listen 80; # 监听端口 80 location / { # 匹配所有请求路径 return 200 "hello nginx"; # 直接返回状态码 200 和响应体 } } }四、常用功能示例
4.1 静态资源服务
Nginx 托管静态文件(HTML / CSS / JS / 图片)非常高效,核心是利用sendfile零拷贝,不占用用户态内存,性能极高。
server { listen 80; # 监听端口 server_name static.ougaii.com; # 域名 sendfile on; # 零拷贝传输文件(高性能) tcp_nopush on; # 合并数据包后发送 location /static/ { # 匹配 /static/ 开头的请求 alias /data/www/static/; # 文件实际路径(替换 /static/ 部分) expires 30d; # 让浏览器缓存资源 30 天 } location / { root /data/www; # 站点根目录 index index.html; # 默认首页 } }说明:
- tcp_nopush:开启数据包缓冲池,当缓冲池满了再返回,避免频繁占用网络。
- alias:替换掉 location 匹配部分,用 alias 的路径去查找资源。和
root二选一使用。root是根目录拼接 location 匹配部分,然后去查找资源。
4.2 动静分离
动静分离就是把静态资源(HTML / CSS / JS / 图片)交给 Nginx 直出,动态请求转给后端处理,可以减轻后端服务器的压力。
server { listen 80; # 监听端口 server_name www.ougaii.com; # 域名 # ========== 静态资源(Nginx 直出) ========== location /static/ { root /var/www; # 资源文件存放目录 /var/www/static/ expires 7d; # 让浏览器缓存资源 7 天 } # ========== 动态请求(转发后端) ========== location /api/ { # 后端 API 接口 proxy_pass http://127.0.0.1:8080; # 转发给后端服务 } }4.3 反向代理
正向代理和反向代理的区别,取决于用户是否主动使用了代理服务器。
正向代理
用户主动选择使用代理服务器,然后通过代理服务器去访问目标地址。目标服务全程根本不知道真实用户的 IP。
常用于 翻墙/VPN,用户主动选择一个代理服务器节点,然后通过代理服务器去访问目标地址。
反向代理
用户不知道自己访问的代理服务器,代理服务器将用户请求转发给目标地址。
常用于 项目部署中,如,统一入口、隐藏后端地址,负载均衡等。
Nginx 设置反向代理,客户端请求打到 Nginx,Nginx 再转发给后端:
server { listen 80; # 监听端口 server_name api.ougaii.com; # 域名 location /api/ { proxy_pass http://127.0.0.1:8080/; # 转发到后端 # ---- 传递客户端真实信息 ---- proxy_set_header Host $host; # 原始请求的 Host proxy_set_header X-Real-IP $remote_addr; # 客户端真实 IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 完整代理链 proxy_set_header X-Forwarded-Proto $scheme; # 请求协议 http/https # ---- 超时控制 ---- proxy_connect_timeout 60s; # 连接后端超时(指定时间内能否连接通) proxy_read_timeout 60s; # 读取后端响应超时(指定时间内,后端能否返回) proxy_send_timeout 60s; # 发送请求给后端超时(指定时间内,能否将数据发送给后端) } }注意 proxy_pass 末尾有无/的区别:
location /api/ { proxy_pass http://localhost:3000/; # 请求 /api/user → 转发成 http://127.0.0.1:8080/user(会去掉 /api/) proxy_pass http://localhost:3000; # 请求 /api/user → 转发成 http://127.0.0.1:8080/api/user/ }4.4 负载均衡
定义一个集群,Nginx 通过负载均衡策略计算后,将请求分发到集群中最合适的服务上。支持的策略:
- 轮询(默认):按请求顺序轮流分配,支持
weight权重 least_conn:分配给当前连接数最少的节点ip_hash:同一客户端 IP 固定分配到同一节点,解决 Session 问题hash $request_uri:按指定 key 哈希分配random:随机分配
http { upstream 自定义集群名称 { # 定义一个上游服务器组(集群) # 默认轮询算法 server 10.0.0.1:8080; # 后端服务 1 server 10.0.0.2:8080; # 后端服务 2 server 10.0.0.4:8080 backup; # 备用节点,其他全挂时启用 } server { listen 80; # 监听端口 server_name app.ougaii.com; # 域名 location / { proxy_pass http://自定义集群名称; # 反向代理到集群 } } }4.5 URL 重写
用于地址跳转、伪静态、强制 HTTPS 等场景:
server { listen 80; # 监听端口 server_name app.ougaii.com; # 域名 # 通过路径重写实现伪静态 location / { # 把 /article/123.html 重写成 /article?id=123 转给后端 rewrite ^/article/(\d+).html$ /article?id=$1 last; # 转发给后端 proxy_pass http://127.0.0.1:8080; } }说明
其中 rewrite 一行中,最后的 last 代表用新 URL 重新匹配当前 server 里的 location
4.6 跨域处理(CORS)
我的其他笔记中详细记载了关于跨域的内容,这里简单且不严谨的解释一下跨域。
前端使用 AJAX 或 Iframe 提交请求时,浏览器为了防止 CSRF 攻击,会判断是否为同域资源访问,流程为:
- 发送一个预检请求(OPTIONS)
- 浏览器根据返回的响应头中的信息判断是否可以访问
- 验证成功,正式发送请求
location /api/ { # ---- 正式请求时:允许跨域的请求 ---- add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; # 允许的 HTTP 方法 add_header Access-Control-Allow-Headers "Content-Type, Authorization"; # 允许的自定义头 add_header Access-Control-Allow-Credentials true; # ---- 预检请求时,允许跨域的请求 ---- if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization"; add_header Access-Control-Allow-Credentials true; add_header Content-Length 0; # 无需响应体 return 204; # 204 No Content } proxy_pass http://127.0.0.1:8080; # 转发到后端接口 }说明:
- Access-Control-Allow-Origin: 发送请求的域名(不是要请求的域名)
- Access-Control-Allow-Methods: 允许的 HTTP 方法
- Access-Control-Allow-Headers: 允许的自定义请求头
- Access-Control-Allow-Credentials: 允许 Cookies
4.7 防盗链
防止其他网站直接引用你的静态资源,消耗你的带宽:
location /static/ { # ---- 防盗链规则,只允许同域名访问 ---- valid_referers server_names; if ($invalid_referer) { # 来源不在上面规则中 return 403; # 拒绝访问或返回一个默认资源 } }说明:
valid_referers 有四种类型,可追加使用,如:valid_referers none blocked server_names *.ougaii.com:
none:允许直接访问(无 Referer)blocked:允许 Referer 被防火墙/代理隐藏的情况server_names:允许当前域名自定义允许通过的域名:如 *.ougaii.com
4.8 限流
防止某个 IP 请求太频繁或连接数太多,打垮后端:
http { # ---- 定义限流规则(放在 http 块,全局生效) ---- # $binary_remote_addr 按【客户端IP】限流 # zone=api_limit:10m 规则名叫 api_limit,分配 10M 内存存 【IP + 请求次数计数器】 # rate=10r/s; 速度:每秒最多 10 个请求 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; # $binary_remote_addr 按IP限制 # zone=conn_limit:10m; 规则名叫 conn_limit,分配 10M 内存存 【IP + 连接数计数器】 limit_conn_zone $binary_remote_addr zone=conn_limit:10m; server { listen 80; # 监听端口 server_name api.ougaii.com; # 域名 location /api/ { # ---- 请求频率限制 ---- # zone=api_limit 用上面的规则 # burst=20 允许一个IP一秒钟内流量突增 20 个,算上原来的 10 个,即 一秒钟最多可以 30 个 # 超过20个不等待,直接处理/拒绝 limit_req zone=api_limit burst=20 nodelay; # ---- 并发连接限制 ---- # conn_limit 20 用上面的规则,每个 IP 最多 20 个并发连接 limit_conn conn_limit 20; limit_req_status 429; # 超限时返回状态码(默认 503) limit_conn_status 503; # 超限时返回状态码 proxy_pass http://127.0.0.1:8080; } } }两个维度的区别:
limit_req:控制请求频率,适合防突发刷接口,例:1 秒最多 10 次limit_conn:控制并发数量,适合防大量长连接占用,例:一个 IP 最多开 20 个连接
五、生产环境常用配置
以下是一份生产环境可用的 nginx.conf 示例,涵盖优化、压缩、日志、限流等:
# ========== 全局配置 ========== user nginx; # Worker 进程运行用户 worker_processes auto; # Worker 数量 = CPU 核心数,充分利用多核 error_log /var/log/nginx/error.log warn; # 错误日志路径,级别 warn(生产足够) pid /var/run/nginx.pid; # PID 文件路径 # ========== 事件模型 ========== events { worker_connections 65535; # 单 Worker 最大连接数 use epoll; # Linux 高性能事件模型(自动选择,可不写) multi_accept on; # 一次 accept 多个连接,提升吞吐 } # ========== HTTP 核心 ========== http { include /etc/nginx/mime.types; # MIME 类型映射 default_type application/octet-stream; # 未知类型默认以流形式下载 # ---- 日志格式 ---- 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 buffer=32k flush=5s; # 缓冲写日志,减少磁盘 I/O # ---- 高效传输 ---- sendfile on; # 零拷贝传输文件 tcp_nopush on; # 合并数据包再发送,提升网络利用率 tcp_nodelay on; # 禁用 Nagle 算法,减少网络延迟 # ---- 长连接 ---- keepalive_timeout 65; # 长连接超时时间 keepalive_requests 1000; # 单连接最大请求数(防内存泄漏) # ---- 请求限制 ---- client_max_body_size 10m; # 允许客户端上传最大文件大小 client_body_buffer_size 128k; # 请求体缓冲区大小 # ---- 文件缓存 ---- open_file_cache max=1000 inactive=20s; # 缓存文件句柄,减少磁盘 I/O open_file_cache_valid 30s; # 缓存有效期 open_file_cache_min_uses 2; # 访问 2 次以上才缓存 open_file_cache_errors on; # 缓存文件错误信息 # ---- Gzip 压缩 ---- gzip on; # 开启响应压缩 gzip_min_length 1000; # 小于 1KB 不压,太小了没意义 gzip_comp_level 6; # 压缩等级(1-9,6 是性价比平衡点) gzip_types text/plain text/css application/json application/javascript text/xml; gzip_vary on; # 添加 Vary: Accept-Encoding 头,缓存友好 gzip_proxied any; # 代理请求也压缩 # ---- 限流定义 ---- limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; # 定义限流区域 limit_conn_zone $binary_remote_addr zone=conn_limit:10m; # 定义连接限制 # ---- 站点配置 ---- server { listen 80; server_name example.com; # 静态资源 location /static/ { root /var/www; expires 7d; add_header Cache-Control "public, immutable"; } # API 接口(反向代理 + 限流) location /api/ { limit_req zone=api_limit burst=20 nodelay; # 请求限流 limit_conn conn_limit 20; # 连接数限制 proxy_pass http://127.0.0.1:8080; 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 60s; proxy_read_timeout 60s; proxy_send_timeout 60s; proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; } # 其他请求 location / { root /var/www/dist; index index.html; try_files $uri $uri/ /index.html; } } }六、常用指令
# ====== 启动 / 停止 / 重载 ======nginx# 启动 Nginxnginx-sstop# 强制停止nginx-squit# 优雅停止(处理完当前请求再停)nginx-sreload# 热重载配置(不中断服务)nginx-sreopen# 重新打开日志文件(日志轮转时用)# ====== 配置检查 ======nginx-t# 测试配置语法是否正确nginx-T# 测试配置并打印完整配置(含 include 展开)# ====== 查看信息 ======nginx-v# 查看版本号nginx-V# 查看版本号 + 编译参数(有哪些模块一目了然)psaux|grepnginx# 查看 Nginx 进程运行状态lsof-i:80# 查看 80 端口被谁占用(排错用)# ====== Nginx 信号管理 ======kill-HUP$(cat/var/run/nginx.pid)# 等价于 nginx -s reload,重载配置kill-USR1$(cat/var/run/nginx.pid)# 等价于 nginx -s reopen,重新打开日志kill-USR2$(cat/var/run/nginx.pid)# 平滑升级二进制文件