nginx概念及使用
一、Nginx 核心概念
Nginx(发音为 "engine-x")是一个高性能、开源的 Web 服务器和反向代理服务器,由俄罗斯工程师伊戈尔・赛索耶夫(Igor Sysoev)于 2004 年开发,最初用于解决当时高并发场景下 Apache 服务器的性能瓶颈问题。
核心特点:
- 高并发低资源消耗:采用异步非阻塞(epoll/kqueue)的事件驱动模型,单台服务器可轻松处理数万并发连接,内存占用仅几十 MB(对比 Apache 的进程 / 线程模型,资源消耗更高)。
- 模块化设计:核心功能通过模块化扩展(如 HTTP、邮件代理、TCP/UDP 代理),支持动态加载模块(需编译时启用)。
- 反向代理与负载均衡:原生支持反向代理、负载均衡(轮询、权重、IP 哈希、最少连接等策略),是微服务架构中 API 网关的常见选择。
- 静态资源处理高效:对静态文件(HTML/JS/CSS/ 图片)的响应速度远超 Apache,支持文件缓存、压缩(gzip/brotli)、范围请求(断点续传)。
- 高可靠性:支持热重载(
nginx -s reload
),修改配置无需重启服务;Worker 进程独立运行,单个进程崩溃不影响整体服务。
二、Nginx 典型应用场景
Nginx 凭借其性能优势,广泛应用于以下场景:
1. 静态 Web 服务器
作为静态资源(HTML / 图片 / 视频)的托管服务器,比 Apache 更高效。例如:托管企业官网、前端框架(React/Vue)构建的静态站点。
2. 反向代理服务器
反向代理是 Nginx 最核心的用途之一:客户端请求先到 Nginx,由 Nginx 转发到后端真实服务器(如 Tomcat/Node.js/PHP-FPM),隐藏后端服务器细节,提升安全性。
3. 负载均衡器
通过配置多台后端服务器,Nginx 可将请求按策略(轮询、权重、IP 哈希等)分发给不同服务器,避免单节点压力过大,提升系统可用性。
4. API 网关
结合 Nginx 的请求路由、协议转换(HTTP/HTTPS)、流量控制(速率限制)、安全过滤(请求头修改、黑白名单)等功能,作为微服务架构的入口网关。
5. HTTP 缓存服务器
通过proxy_cache
指令缓存后端服务器的响应结果,减少重复请求对后端的压力,提升用户访问速度(如缓存静态资源或高频动态接口)。
三、Linux 系统安装 Nginx
方式 1:通过包管理器安装(推荐)
# 更新包索引
sudo apt update
# 安装Nginx
sudo apt install nginx -y
# 启动服务并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx
方式 2:源码编译安装(自定义功能)
适合需要定制模块(如ngx_http_ssl_module
/ngx_http_realip_module
)或更高版本的场景:
# 安装依赖
sudo apt install gcc make libpcre3-dev zlib1g-dev openssl-dev -y # Ubuntu
# 或 sudo yum install gcc make pcre-devel zlib-devel openssl-devel -y (CentOS)# 下载源码(以1.24.0版本为例)
wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0# 配置编译参数(启用SSL、gzip等模块)
./configure \--prefix=/usr/local/nginx \ # 安装路径--with-http_ssl_module \ # 启用HTTPS支持--with-http_gzip_static_module \ # 启用gzip静态压缩--with-http_realip_module # 启用真实IP获取(反向代理场景)# 编译并安装
make && sudo make install
例如我的./configure如下:
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_addition_module --with-http_ssl_module --with-http_gzip_static_module --with-http_secure_link_module --with-http_stub_status_module --with-stream --with-pcre=/home/jerry/snap/nginx/pcre-8.45 --with-zlib=/home/jerry/snap/nginx/zlib-1.2.13 --with-openssl=/home/jerry/snap/nginx/openssl-1.1.1s
四、Nginx 核心配置解析
Nginx 的配置文件默认位于 /etc/nginx/nginx.conf
(包管理器安装)或 /usr/local/nginx/conf/nginx.conf
(源码安装),采用模块化层级结构,核心包含 3 大块:
1. 主配置块(main)
全局配置,影响所有模块,例如:
user www-data; # 运行Nginx的用户/用户组(Ubuntu默认www-data)
worker_processes auto; # Worker进程数(建议设置为CPU核心数,auto自动检测)
error_log /var/log/nginx/error.log warn; # 错误日志路径及级别(debug/info/warn/error)
pid /run/nginx.pid; # 主进程PID文件路径# 事件模块配置(events块)
events {worker_connections 1024; # 每个Worker进程最大并发连接数use epoll; # 指定事件驱动模型(Linux推荐epoll,FreeBSD用kqueue)
}
当
worker_processes auto;
配置下开启四个进程(worker),且 Nginx 配置文件监听四个端口(9000~9003)时,完整连接处理过程如下:
Nginx 启动阶段
- Master 进程读取配置文件,创建 9000~9003 端口的监听套接字(fd),并开始监听。
- Master 进程通过
fork()
生成四个 worker 进程。每个 worker 进程继承 master 的监听套接字(fd),此时所有 worker 进程共享这四个端口的监听。连接请求到达时
- 当客户端向某一端口(如 9000)发起连接请求,内核通过负载均衡机制(如
SO_REUSEPORT
特性避免惊群效应)选择一个 worker 进程处理该连接。- 被选中的 worker 进程调用
accept()
接受连接,生成新的连接套接字(fd),并将该 fd 添加到自身的epoll
实例中管理。- 后续该连接的读 / 写事件由该 worker 进程通过
epoll
监听和处理(如读取客户端请求、返回响应等)。多端口与负载均衡
- 对于 9001~9003 端口,流程类似:每个端口的连接请求由内核分配给某个 worker 进程,worker 进程处理连接并通过自身
epoll
管理。- 四个 worker 进程各自独立维护自己的
epoll
实例,分别处理不同端口的连接请求,实现多进程并发处理,充分利用多核性能。事件循环与资源管理
- 每个 worker 进程在自己的事件循环中通过
epoll
监听连接套接字的事件(如可读、可写)。- 当连接关闭或发生异常时,worker 进程从
epoll
中移除对应 fd,并释放相关资源。
2. HTTP 块(http)
定义 HTTP 相关的核心功能,如虚拟主机、反向代理、缓存等,支持嵌套server
(虚拟主机)和location
(路径匹配)块:
http {# 全局HTTP配置(对所有server生效)include /etc/nginx/mime.types; # MIME类型映射文件default_type application/octet-stream; # 默认MIME类型(未匹配时)# 日志格式定义(可自定义字段)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; # 访问日志路径及格式# 连接超时设置send_timeout 60; # 发送响应超时时间(秒)keepalive_timeout 75; # 长连接超时时间# 静态资源优化(gzip压缩)gzip on;gzip_min_length 1k; # 最小压缩文件大小(小于1KB不压缩)gzip_types text/plain text/css application/json application/javascript; # 压缩类型# 虚拟主机(server块,可定义多个)server {listen 80; # 监听端口server_name example.com www.example.com; # 绑定域名(支持通配符如*.example.com)root /var/www/example; # 网站根目录(静态文件路径)index index.html index.htm; # 默认索引文件# 路径匹配(location块)location / {try_files $uri $uri/ =404; # 尝试访问文件/目录,不存在返回404}# 反向代理示例(转发/api开头的请求到后端Node.js服务)location /api/ {proxy_pass http://127.0.0.1:3000/; # 后端服务器地址(注意末尾的/)proxy_set_header Host $host; # 传递原始请求头到后端proxy_set_header X-Real-IP $remote_addr; # 传递真实客户端IPproxy_connect_timeout 10; # 连接后端超时时间(秒)}# 错误页面配置error_page 404 /404.html;error_page 500 502 503 504 /50x.html;}
}
以下是我写的问卷系统使用的nginx.conf,解析以及优化建议如下:
user root; worker_processes 1;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;client_max_body_size 30m;# 添加以下配置,用于设置全局的跨域相关响应头,允许所有域名跨域访问(生产环境可按需修改为指定域名)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';server {listen 80;server_name localhost;#index index.html index.htm default.htm default.html;root /home/jerry/Desktop/questionnare/questionnare-front;location /login {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /login.html;# 针对这个具体的location块,也可以单独配置更细化的跨域头信息,以下是示例(如果全局配置满足需求可不加)# add_header 'Access-Control-Allow-Origin' '*';# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';# add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';# add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /reg {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /reg.html;}location /survey {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /survey.html;}location /root {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root.html;}location /root_create_table{ #在root的开始界面的创建新的问卷#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root_create_table.html;}location /root_table {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root_table.html;}location /table {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /table.html;}# api相关location块location /api/mypictures{proxy_pass http://127.0.0.1:8081;# 针对/api开头的这些接口相关location块,也添加跨域头信息(可根据实际需求决定是否和全局配置保持一致或者单独配置)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}# api相关location块location /api/mytables{proxy_pass http://127.0.0.1:8081;# 针对/api开头的这些接口相关location块,也添加跨域头信息(可根据实际需求决定是否和全局配置保持一致或者单独配置)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/login{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/reg{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/unreg{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/upload{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/delete{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/tables{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/table_delete{ #删除特定的表格proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/table_create{ #删除特定的表格proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}# 添加 Lua 脚本的 location 块location /test_login {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_login.lua;}location /test_questionnare {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_questionnare.lua;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }
一、全局配置块
user root;
- 作用:指定 Nginx 工作进程运行的用户和用户组(默认
nobody
)。- 注意:
- 开发环境可临时使用
root
,但生产环境严禁使用(权限过高存在安全风险),建议创建专用用户(如nginx
或www-data
)。- 配置格式:
user <用户名> [<用户组>]
,如user nginx nginx;
。worker_processes 1;
- 作用:设置 Nginx 工作进程(Worker)的数量。
- 解析:
1
表示仅启动 1 个 Worker 进程,适用于单核心 CPU 或开发环境。- 生产环境建议:设为
auto
(自动检测 CPU 核心数)或显式指定核心数(如worker_processes 4;
),充分利用多核性能。二、事件模块(
events
块)events {worker_connections 1024; }
- 作用:配置 Worker 进程的连接处理策略。
- 解析:
worker_connections 1024
:每个 Worker 进程最多可同时处理的连接数(含监听连接和客户端连接)。- 理论最大并发连接数:
worker_processes * worker_connections
,即此处为1×1024=1024
。- 生产环境建议:根据内存调整,通常设为
10240
或更高(如worker_connections 8192;
)。三、HTTP 核心配置(
http
块)http {include mime.types;default_type application/octet-stream;
include mime.types
:引入 MIME 类型映射文件(默认路径/etc/nginx/mime.types
),用于识别文件类型(如.js
对应application/javascript
)。default_type application/octet-stream
:未匹配到 MIME 类型的文件,默认以二进制流形式处理(避免浏览器误解析)。sendfile on;
- 作用:启用
sendfile
系统调用(零拷贝技术),提升静态文件传输效率(减少内核空间与用户空间的数据拷贝)。- 适用场景:静态资源服务器、文件下载等场景,建议始终开启(默认
off
)。keepalive_timeout 65;
- 作用:设置 HTTP 长连接的超时时间(秒)。
- 解析:客户端与 Nginx 建立的连接在空闲
65
秒后自动关闭,减少无效连接占用资源。client_max_body_size 30m;
- 作用:限制客户端请求体的最大大小(含文件上传)。
- 场景:适用于需要上传文件的场景(如图片、文档),
30m
表示允许最大 30MB 的请求体。四、全局跨域配置
# 全局跨域头(开发环境可用 *,生产环境需限制具体域名)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
- 作用:解决前端与后端的跨域问题(CORS)。
- 解析:
Access-Control-Allow-Origin: *
:允许所有域名跨域(开发环境方便,但生产环境需改为具体域名,如add_header 'Access-Control-Allow-Origin' 'https://example.com';
)。OPTIONS
请求处理:前端发送跨域请求时会先发送OPTIONS
预检请求,需允许OPTIONS
方法。- 优化建议:将跨域头移至
http
块顶部,避免在每个location
重复配置。五、虚拟主机(
server
块)server {listen 80;server_name localhost;
listen 80
:监听 HTTP 80 端口。server_name localhost
:绑定域名或 IP(此处为本地开发环境,仅响应localhost
的请求)。root /home/jerry/Desktop/questionnare/questionnare-front;
- 作用:设置当前虚拟主机的根目录,用于解析静态文件路径。
- 示例:当请求
/login.html
时,Nginx 会查找路径/home/jerry/Desktop/questionnare/questionnare-front/login.html
。六、静态资源路由(
location
块)1.
/login
路由location /login {try_files $uri $uri/ /login.html;}
- 作用:处理
/login
路径的请求。- 解析:
try_files $uri $uri/ /login.html;
:
- 先尝试访问请求的 URI(如
/login
)对应的文件或目录;- 若不存在,则返回根目录下的
login.html
文件(实现前端路由匹配,避免 404)。- 适用场景:SPA(单页应用)路由,如 Vue/React 的前端路由。
2. 其他静态路由(
/reg
,/survey
等)location /reg {try_files $uri $uri/ /reg.html;}# 省略 `/survey`, `/root` 等类似配置...
- 作用:与
/login
逻辑一致,分别映射到reg.html
,survey.html
等前端页面。七、API 反向代理(
location
块)1.
/api/mypictures
接口location /api/mypictures{proxy_pass http://127.0.0.1:8081;# 跨域头(全局已配置,此处可省略)add_header 'Access-Control-Allow-Origin' '*';# ... 省略重复的跨域头配置 ...}
- 作用:将以
/api/mypictures
开头的请求转发到后端服务器http://127.0.0.1:8081
。- 解析:
proxy_pass
:反向代理的目标地址,末尾不带/
时,请求路径会保留前缀(如/api/mypictures
转发为http://127.0.0.1:8081/api/mypictures
)。- 跨域头优化:全局
http
块已配置跨域头,此处可删除重复的add_header
,避免响应头冗余。2. 其他 API 接口(
/api/login
,/api/upload
等)location /api/login{proxy_pass http://127.0.0.1:8081;# ... 省略重复的跨域头配置 ...}
- 共性:所有
/api/
开头的路径均转发到后端8081
端口,适用于前后端分离架构(前端跑在 Nginx,后端为独立服务)。- 建议优化:
location /api/ { # 统一匹配所有 /api/ 路径proxy_pass http://127.0.0.1:8081;proxy_set_header Host $host; # 传递原始 Host 头proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP }
合并为一个location
块,避免重复代码,提升可维护性。八、Lua 脚本支持(动态请求处理)
location /test_login {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_login.lua;}
- 作用:通过
ngx_lua
模块执行 Lua 脚本,动态生成响应内容(如测试接口、自定义逻辑)。- 依赖:需提前编译 Nginx 并启用
ngx_lua
模块(--add-module=/path/to/ngx_lua
)。- 示例场景:
- 临时测试接口逻辑;
- 动态生成验证码、签名等。
九、错误页面配置
error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}
- 作用:当后端返回 500 系列错误时,Nginx 自动返回
50x.html
页面。- 解析:
root html;
:50x.html
的实际路径为 Nginx 默认的html
目录(通常为/usr/share/nginx/html
或编译时指定的路径)。- 注意:若前端项目的错误页面在根目录(如
/home/jerry/.../50x.html
),需将root
指向前端目录:location = /50x.html {root /home/jerry/Desktop/questionnare/questionnare-front; }
十、优化建议与注意事项
1. 生产环境改进点
- 用户权限:
user nginx nginx; # 创建专用用户(需先 `useradd nginx`)
- Worker 进程数:
worker_processes auto; # 自动适配 CPU 核心数
- 跨域安全:
add_header 'Access-Control-Allow-Origin' 'https://your-domain.com'; # 限制具体域名
- 合并 API 代理:
将多个/api/
路径合并为一个location
块,减少配置冗余。2. 性能优化
- 开启 Gzip 压缩:
gzip on; gzip_types text/plain text/css application/json application/javascript;
- 静态资源缓存:
location /api/ { # 统一匹配所有 /api/ 路径proxy_pass http://127.0.0.1:8081;proxy_set_header Host $host; # 传递原始 Host 头proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP }
3. 安全加固
- 禁止直接访问敏感文件:
location ~* \.(php|sh|bak|swp)$ {deny all; # 禁止访问 PHP、脚本文件、备份文件等 }
- 隐藏 Nginx 版本号:
server_tokens off;
五、Nginx 常用操作命令
命令 | 说明 |
---|---|
sudo nginx | 启动 Nginx 服务 |
sudo nginx -s stop | 强制停止服务(立即终止所有连接) |
sudo nginx -s quit | 优雅停止服务(完成当前请求后退出) |
sudo nginx -s reload | 重新加载配置文件(热更新,推荐) |
sudo nginx -t | 检查配置文件语法是否正确 |
sudo nginx -v | 查看 Nginx 版本信息 |
六、Nginx 性能调优建议
- Worker 进程数:设置为 CPU 核心数(
worker_processes auto
),避免进程竞争。 - 连接数优化:
worker_connections
设为 10240(根据内存调整),配合multi_accept on
(允许 Worker 进程一次性接受多个连接)。 - 静态资源缓存:通过
expires
指令设置客户端缓存时间(如图片 / JS/CSS 缓存 30 天)。 - 压缩配置:启用
gzip
或brotli
压缩,减少传输流量(仅对文本类文件有效)。 - 日志优化:对静态资源关闭访问日志(
access_log off;
),减少 I/O 消耗。
七、常见问题排查
- 502 Bad Gateway:通常是后端服务器无响应(检查后端服务是否启动、端口是否开放)。
- 403 Forbidden:可能是 Nginx 用户(
user
)无权限访问网站目录(检查目录权限chmod
)。 - 配置修改不生效:未执行
nginx -s reload
(需重载配置)或配置文件语法错误(通过nginx -t
检查)。 - 日志查看:
- 访问日志:
/var/log/nginx/access.log
(记录所有请求) - 错误日志:
/var/log/nginx/error.log
(记录异常信息)
- 访问日志:
八、反向代理(Reverse Proxy)
1. 核心原理
- 角色定位:Nginx 作为客户端的「代理服务器」,接收所有外部请求,根据规则转发到后端真实服务器(如 Tomcat/Node.js/Java 服务),并将响应返回给客户端。
- 核心作用:
- 隐藏后端服务器架构(IP、端口等细节),提升安全性;
- 统一处理跨域、认证、日志等公共逻辑,简化后端开发;
- 支持协议转换(如 HTTP ↔ HTTPS、WebSocket 代理)。
2. 典型配置场景
场景 1:基础 HTTP 反向代理
需求:将 http://api.example.com
的请求转发到后端 192.168.1.100:8080
服务,并传递真实客户端 IP。
配置示例:
server {listen 80;server_name api.example.com;location / {# 转发请求到后端服务器(注意结尾的/,与location路径匹配)proxy_pass http://192.168.1.100:8080/;# 传递原始请求头(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_connect_timeout 5s;proxy_read_timeout 30s;proxy_send_timeout 30s;}
}
场景 2:HTTPS 反向代理(代理 HTTPS 后端服务)
需求:后端服务使用 HTTPS 协议(如 Java Spring Boot 服务),Nginx 需转发 HTTPS 请求。
配置示例:
server {listen 80;server_name secure-api.example.com;location / {# 转发到 HTTPS 后端(协议为 https://)proxy_pass https://192.168.1.101:8443/;# 信任后端证书(若为自签名证书需添加)proxy_ssl_verify off;proxy_ssl_certificate /path/to/backend_cert.pem; # 可选:验证后端证书时使用}
}
场景 3:WebSocket 反向代理
需求:支持前端 WebSocket 连接(ws://chat.example.com
),转发到后端 WebSocket 服务。
配置示例:
server {listen 80;server_name chat.example.com;location / {# 转发 WebSocket 请求(需切换协议头)proxy_pass http://192.168.1.102:8080;# 关键配置:升级协议为 WebSocketproxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";}
}
场景 4:路径重写反向代理
需求:将 http://example.com/app/
路径的请求转发到后端 http://backend:3000/
,并去除路径前缀 /app
。
配置示例:
server {listen 80;server_name example.com;location /app/ {# 去除路径前缀 /app,转发到后端根路径proxy_pass http://backend:3000/;rewrite ^/app/(.*) /$1 break; # 重写路径# 其他通用配置proxy_set_header Host $host;}
}
3. 验证方法
-
检查请求头:
后端服务中打印X-Real-IP
或X-Forwarded-For
头,确认是否为客户端真实 IP。# 示例:用 curl 模拟请求并查看响应头 curl -H "Host: api.example.com" http://localhost/app/
-
日志验证:
在 Nginx 访问日志中添加$upstream_addr
字段,查看请求转发的后端地址:log_format proxy_log '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$upstream_addr"'; access_log /var/log/nginx/proxy_access.log proxy_log;
九、负载均衡(Load Balancing)高级应用
1. 负载均衡策略详解
Nginx 支持多种分配策略,通过 upstream
块配置:
策略 | 说明 | 适用场景 |
---|---|---|
轮询 | 默认策略,依次将请求分发给后端服务器(权重相同则均匀分配)。 | 无状态服务,服务器性能一致。 |
权重 | weight 参数指定服务器处理能力(如 weight=3 表示处理 3 倍请求)。 | 服务器性能不均场景。 |
IP 哈希 | 按客户端 IP 的哈希值固定路由到某台服务器(会话保持)。 | 需要会话保持的场景。 |
最少连接 | 优先将请求分发给当前连接数最少的服务器。 | 长连接较多的场景(如下载服务)。 |
URL 哈希 | 按请求 URL 的哈希值路由(需第三方模块 ngx_http_upstream_hash )。 | 相同 URL 需固定到同一服务器(如静态资源缓存)。 |
动态权重 | 根据服务器响应时间动态调整权重(需第三方模块 ngx_http_upstream_least_time )。 | 实时动态负载均衡。 |
2. 典型配置示例
场景 1:轮询策略(默认)
需求:将请求均匀分发给 3 台后端服务器。
配置示例:
http {upstream web_app {server 192.168.1.101:8080;server 192.168.1.102:8080;server 192.168.1.103:8080;}server {listen 80;server_name lb.example.com;location / {proxy_pass http://web_app;proxy_set_header Host $host;}}
}
场景 2:权重策略(性能差异化)
需求:2 台高性能服务器(权重 2)和 1 台低性能服务器(权重 1)。
配置示例:
upstream web_app {server 192.168.1.101:8080 weight=2;server 192.168.1.102:8080 weight=2;server 192.168.1.103:8080 weight=1;
}
场景 3:IP 哈希(会话保持)
需求:确保同一客户端的请求始终路由到同一服务器(如电商购物车场景)。
配置示例:
upstream web_app {ip_hash; # 启用 IP 哈希策略server 192.168.1.101:8080;server 192.168.1.102:8080;
}
场景 4:最少连接策略
需求:优先将请求分发给当前负载较低的服务器(如视频流媒体服务)。
配置示例:
upstream web_app {least_conn; # 启用最少连接策略server 192.168.1.101:8080;server 192.168.1.102:8080;
}
场景 5:健康检查(避免转发到故障节点)
需求:自动剔除不可用的后端服务器,并在恢复后重新加入集群。
配置示例(需启用 ngx_http_upstream_module
):
upstream web_app {server 192.168.1.101:8080 max_fails=2 fail_timeout=30s; # 2次失败则标记为不可用,30s后重试server 192.168.1.102:8080;server 192.168.1.103:8080 down; # 手动标记为下线(维护状态)
}
3. 高级配置:会话保持与缓存
会话保持(Sticky Cookies)
通过 Cookie 实现会话固定,确保同一客户端请求始终路由到同一服务器:
upstream web_app {server 192.168.1.101:8080;server 192.168.1.102:8080;# 生成名为 "sticky" 的 Cookie,值为后端服务器的哈希值sticky cookie srv_id expires=1h domain=.example.com path=/;
}
缓存响应结果
通过 proxy_cache
减少后端压力,缓存高频请求结果:
http {# 定义缓存区域(内存+磁盘)proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;proxy_cache_key "$scheme$host$request_uri"; # 缓存键规则upstream web_app {server 192.168.1.101:8080;}server {location / {proxy_pass http://web_app;proxy_cache my_cache; # 启用缓存proxy_cache_valid 200 302 1h; # 对200/302响应缓存1小时proxy_cache_valid 404 1m; # 对404响应缓存1分钟}}
}
4. 验证负载均衡效果
-
模拟请求分发:
使用curl
配合循环脚本,发送多个请求并观察后端服务器日志:# 循环发送10次请求,查看响应来自哪台服务器 for i in {1..10}; do curl http://lb.example.com; done
-
压力测试:
使用ab
(Apache Benchmark)工具测试负载均衡均匀性:ab -n 1000 -c 10 http://lb.example.com/
统计结果中
Requests per second
应接近后端服务器数量的倍数(如 3 台服务器则 QPS 约为单台的 3 倍)。 -
查看 Nginx 状态页:
启用ngx_http_stub_status_module
查看 upstream 状态:location /status {stub_status on;access_log off;allow 127.0.0.1; # 仅允许本地访问deny all; }
访问
http://nginx_ip/status
可查看活跃连接数、请求总数等指标。
0voice · GitHub