【Nginx 从入门到实践:6 大核心场景全解析(配置 + 安装 + 代理 + 虚拟主机)】
总结nginx的配置结构和流量访问逻辑过程
一、Nginx 配置结构
Nginx 配置采用层次化、模块化的结构,主要由以下几个层级组成:
1. 全局块(Global Block)
位于配置文件最顶部,设置影响 Nginx 全局运行的参数:(/etc/nginx/nginx.conf/vhsot.conf)
user nginx; # 运行用户/组
worker_processes auto; # worker 进程数,通常设为 CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志路径和级别
pid /var/run/nginx.pid; # 进程 PID 文件
2. events 块
配置 Nginx 与客户端的连接处理机制,决定如何响应并发请求:
events {
worker_connections 1024; # 每个 worker 进程最大连接数
use epoll; # 事件驱动模型(Linux 推荐 epoll)
multi_accept on; # 是否允许同时接受多个新连接
}
3. http 块(最核心)
HTTP 服务的主配置容器,包含媒体类型、日志格式、keepalive、压缩等通用配置,以及多个 server 块:
http {
include 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;
sendfile on; # 高效文件传输
tcp_nopush on; # 防止网络阻塞
tcp_nodelay on; # 实时发送数据
keepalive_timeout 65; # 长连接超时时间
gzip on; # 启用 Gzip 压缩
# 包含其他 server 配置文件
include /etc/nginx/conf.d/*.conf;
}
4. server 块(虚拟主机)
每个 server 块代表一个虚拟主机,通过 listen 和 server_name 区分不同的站点:
server {
listen 80; # 监听端口
server_name example.com www.example.com; # 域名匹配
# 该 server 下的 location 规则...
}
5. location 块(URI 路由)
location 是 Nginx 实现请求路由的核心,根据 URI 匹配规则执行不同操作:
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认索引文件
}
location /api/ {
proxy_pass http://backend_server; # 反向代理到后端
}
location ~ \.(gif|jpg|png)$ { # 正则匹配静态图片
root /var/www/images;
expires 30d; # 缓存 30 天
}
location 匹配优先级(重要!):
(1)= 精确匹配(最高优先级)
(2)^~ 前缀匹配(匹配到后停止搜索正则)
(3)~ 和 ~* 正则匹配(区分/不区分大小写)
(4)普通前缀匹配(最长匹配优先)
(5)/ 通用匹配(最低优先级)
二、流量访问逻辑过程(完整生命周期)
当用户浏览器发起一个 HTTP 请求时,Nginx 内部的处理流程如下:
┌─────────────────────────────────────────────────────────────┐
│ 1. 监听阶段 (Listen) │
│ Nginx Master 进程监听端口(如 80/443),等待 TCP 连接 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 2. 连接建立 (Accept) │
│ 新连接到达,Master 分配给某个 Worker 进程(负载均衡) │
│ Worker 通过 epoll/kqueue 事件通知获取连接 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 3. HTTP 请求解析 (Parse Request) │
│ Worker 读取请求行:METHOD URI HTTP_VERSION │
│ 解析请求头 (Headers),构建内部请求结构体 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 4. 虚拟主机匹配 (Server Selection) │
│ 根据 "IP:Port" 找到 listen 匹配的 server 块 │
│ 再根据 Host 头匹配 server_name,确定最终 server 配置 │
│ 若无匹配,使用第一个该端口的 server(默认服务器) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 5. URI 路由匹配 (Location Selection) │
│ 在确定的 server 内,按优先级匹配 location │
│ 找到最佳匹配后,继承/合并该 location 的配置指令 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 6. 请求处理 (Request Processing) │
│ 根据 location 内的指令决定行为: │
│ • root/alias → 静态文件服务 │
│ • proxy_pass → 反向代理到后端(如 Node/Java/PHP) │
│ • fastcgi_pass → FastCGI 协议(如 PHP-FPM) │
│ • return/rewrite → 重定向或重写 │
│ • try_files → 文件存在性检查(常用于前端路由) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 7. 内容生成与过滤 (Content & Filter) │
│ 静态文件:读取磁盘,经过 Gzip 压缩、图片裁剪等过滤模块 │
│ 反向代理:建立与后端连接,转发请求,接收响应 │
│ 响应头处理:添加缓存控制、CORS、安全头等 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 8. 响应发送 (Send Response) │
│ 将 HTTP 响应(状态行 + 响应头 + 响应体)发送给客户端 │
│ 若开启 sendfile,直接内核态传输,零拷贝高效发送 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 9. 日志记录 (Logging) │
│ 按配置的 log_format 写入 access_log │
│ 记录:IP、时间、请求方法、URI、状态码、响应大小、耗时等 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 10. 连接管理 (Connection Management) │
│ 若 keepalive 开启,连接复用等待下一个请求 │
│ 若超时或客户端关闭,释放连接资源 │
└───────────────────────────────────────────────────────────
三、关键流程图解(简化版)
用户请求: GET http://example.com/api/users
┌─────────┐
│ DNS 解析 │ → 获取 IP
└────┬────┘
↓
┌─────────┐
│ TCP 连接 │ → 三次握手到 Nginx:80
└────┬────┘
↓
┌─────────┐
│ Worker 接管│
└────┬────┘
↓
┌──────────────────────────┐
│ 匹配 server: │
│ listen 80 + server_name │
│ example.com │
└────┬───────────────────────┘
↓
┌──────────────────────────┐
│ 匹配 location: │
│ /api/ → proxy_pass │
│ http://backend_server │
└────┬───────────────────────┘
↓
┌─────────┐
│ 反向代理 │ → 转发给后端应用服务器
└────┬────┘
↓
┌─────────┐
│ 后端处理 │ → 数据库查询、业务逻辑...
└────┬────┘
↓
┌─────────┐
│ 返回响应 │ → Nginx 透传/修改后发给客户端
└────┬────┘
↓
┌─────────┐
│ 记录日志 │ → access.log
└─────────┘
注:
记忆口诀:
main(全局) → events(连接) → http(协议) → server(站点) → location(路径)
核心层次说明:
-
main:进程数、日志、运行用户。
-
events:epoll 模型、每个 worker 的连接数。
-
http:全局 HTTP 配置、mime 类型、代理缓存、日志格式。
-
server:虚拟主机,区分不同域名的网站。
-
location:根据请求 URI 执行不同处理(静态文件 / 反向代理 / 重定向)。
搭建nginx完成二进制安装和多OS下的软件包安装过程
准备工作(所有安装方式通用)
-
操作系统:CentOS 、RHEL、Ubuntu 、Debian 等。
-
用户:非 root 最好有 sudo 权限,但为了演示,我会用 root 或 sudo。
-
端口:确保 80 端口没有被占用(
lsof -i:80)。
一、apt 官方仓库安装(推荐常规使用)
1. 安装依赖工具
apt update
apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring

2. 添加 Nginx 官方签名密钥和仓库
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg
# 根据你的 Ubuntu 版本代号(此处为 resolute)添加仓库
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu resolute nginx" > /etc/apt/sources.list.d/nginx.list
3. 安装 Nginx
apt install -y nginx
4. 启动并设置开机自启
systemctl start nginx
systemctl enable nginx

5. 验证
nginx -v
curl -I http://localhost

防火墙放行 80 端口(如果启用了 ufw)
ufw allow 80/tcp
ufw reload
没有启用防火墙可跳过。
注:
常见问题
-
端口 80 被占用:先
lsof -i:80查看,可以systemctl stop apache2或其他 Web 服务。 -
编译时缺少依赖:根据错误提示安装对应的
-dev包。 -
systemd 启动失败:运行
journalctl -u nginx查看日志。
完成nginx https配置,防盗链,重定向相关实践过程
一、准备工作:生成自签名 SSL 证书(测试用)
生产环境应该用 Let's Encrypt 或购买证书,这里为了练习,我们自己签发一个。

生成后文件:test.key(私钥)和 test.crt(证书)。
二、配置 HTTPS 站点
1. 编辑 Nginx 配置文件
用的是 apt 安装,配置文件在 /etc/nginx/conf.d/ 或 /etc/nginx/sites-available/。为了简单,我们直接编辑 /etc/nginx/nginx.conf 里的 server 块,或者新建一个 /etc/nginx/conf.d/https.conf。
用下面内容创建一个新的 server 块,监听 443 ssl:
cat > /etc/nginx/conf.d/https.conf <<EOF
server {
listen 443 ssl;
server_name localhost; # 改成你的域名或IP
ssl_certificate /etc/nginx/ssl/test.crt;
ssl_certificate_key /etc/nginx/ssl/test.key;
# 可选:加强安全(测试环境可以不加)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
2. 创建测试页面
mkdir -p /var/www/html
echo "<h1>HTTPS works!</h1>" > /var/www/html/index.html
3. 检查配置并重启 Nginx
nginx -t # 检查语法
systemctl reload nginx # 或者 nginx -s reload
4. 测试 HTTPS
使用 curl 忽略证书验证:

应该输出 <h1>HTTPS works!</h1>。
也可以用浏览器访问 https://你的服务器IP,会提示不安全(自签名),点击继续即可看到页面。
三、配置重定向(HTTP → HTTPS)
为了让用户访问 http:// 时自动跳转到 https://,添加一个监听 80 的 server 块做 301 重定向。
1. 编辑同一配置文件或新建一个
cat >> /etc/nginx/conf.d/https.conf <<EOF
server {
listen 80;
server_name localhost;
return 301 https://\$host\$request_uri;
}
EOF
注意:$host 会保留原始域名,$request_uri 保留路径和参数。
2. 检查并重载
nginx -t
systemctl reload nginx

3. 测试
curl -I http://localhost/

四、配置防盗链(防止图片/文件被其他网站引用)
防盗链通常通过 valid_referers 指令实现,只允许你自己的域名(或空)访问资源,其他来源返回 403 或指定错误图。
1. 准备测试图片
mkdir -p /var/www/html/images
# 随便找一张图片放到该目录,或者用 base64 生成一个简单图片
echo "fake image content" > /var/www/html/images/test.jpg # 实际应为真实图片,这里仅为演示
2. 在 HTTPS server 块内添加 location 规则
编辑 /etc/nginx/conf.d/https.conf,在 server 块中加入:
location /images/ {
valid_referers none blocked localhost *.yourdomain.com; # 把 yourdomain.com 换成你的实际域名
if ($invalid_referer) {
return 403;
# 或者 return 404; 或者 rewrite ^/images/.*\.(jpg|png)$ /images/steal.png break;
}
try_files $uri =404;
}
解释:
-
valid_referers:允许的来源。none表示直接访问(无 referer),blocked表示 referer 被防火墙或代理去掉(宽松处理),后面是具体的域名。 -
$invalid_referer:如果 referer 不在允许列表,则为 true。 -
if ($invalid_referer) { return 403; }:拒绝盗链请求。

3. 重载并测试
重载配置后,用不同的 Referer 测试:
# 不带 referer(直接访问)应该是允许的
curl -k -s -o /dev/null -w "%{http_code}\n" https://localhost/images/test.jpg
# 伪造 referer 为其他网站
curl -k -e "http://bad.site.com" -s -o /dev/null -w "%{http_code}\n" https://localhost/images/test.jpg
第一个应返回 200,第二个返回 403。

完成nginx虚拟主机配置,包括ip 多端口 多域名相关的配置
一、准备工作
在 Ubuntu 10.0.0.13 上,确保 Nginx 已安装(推荐 apt 官方源)。

创建三个测试网站的根目录:
mkdir -p /var/www/{port80,port8080,domain_a,domain_b,ip2}
echo "<h1>Default Port 80 site</h1>" > /var/www/port80/index.html
echo "<h1>Port 8080 site</h1>" > /var/www/port8080/index.html
echo "<h1>Domain A: siteA.local</h1>" > /var/www/domain_a/index.html
echo "<h1>Domain B: siteB.local</h1>" > /var/www/domain_b/index.html
echo "<h1>IP-based virtual host (10.0.0.14)</h1>" > /var/www/ip2/index.html
二、配置多端口虚拟主机
创建配置文件 /etc/nginx/conf.d/ports.conf:
cat > /etc/nginx/conf.d/ports.conf <<EOF
server {
listen 80;
server_name _;
root /var/www/port80;
index index.html;
}
server {
listen 8080;
server_name _;
root /var/www/port8080;
index index.html;
}
EOF

检查并重载:

测试:

两个命令应返回不同的页面。
三、配置多域名虚拟主机(同一端口 80)
我们需要两个测试域名,例如 siteA.local 和 siteB.local。
cat > /etc/nginx/conf.d/domains.conf <<'EOF'
server {
listen 80;
server_name siteA.local;
root /var/www/domain1;
}
server {
listen 80;
server_name siteB.local;
root /var/www/domain2;
}
EOF
nginx -t && systemctl reload nginx
测试(不需要改任何 hosts,直接用 -H 指定 Host):

完成nginx方向代理和动静分离相关的演示
一、准备环境与目录结构
在 Ubuntu 上执行:
# 创建静态资源目录和一个简单的动态应用目录
mkdir -p /var/www/static
mkdir -p /var/www/dynamic
# 创建静态文件(图片、CSS、HTML)
echo "<h1>This is static page served by Nginx</h1>" > /var/www/static/index.html
echo "body { background: lightblue; }" > /var/www/static/style.css
echo "static image content" > /var/www/static/pic.jpg # 模拟图片
# 创建动态应用的一个简单模拟页面(Python 服务将返回这个)
echo "<h1>Dynamic response from backend (Python HTTP server)</h1>" > /var/www/dynamic/index.html
二、启动后端模拟服务(Python 简单 HTTP 服务器)
我们在 127.0.0.1:8000 启动一个 HTTP 服务,作为动态后端。
cd /var/www/dynamic
nohup python3 -m http.server 8000 --bind 127.0.0.1 > /tmp/python_http.log 2>&1 &

验证后端服务正常:

应显示 <h1>Dynamic response from backend...</h1>。
这个 Python 服务器会返回当前目录下的文件,我们只有
index.html,所以访问根路径就会显示它。
三、配置 Nginx 实现反向代理 + 动静分离
需求说明:
-
所有请求路径以
/static/开头的,由 Nginx 直接返回本地/var/www/static目录下的文件(静态资源)。 -
其他所有请求(比如
/、/api/等)都反向代理到后端 Python 服务http://127.0.0.1:8000。
创建配置文件 /etc/nginx/conf.d/reverse_proxy.conf:
cat > /etc/nginx/conf.d/reverse_proxy.conf <<'EOF'
server {
listen 80;
server_name _; # 接受所有域名
# 静态资源:直接由 Nginx 返回本地文件
location /static/ {
alias /var/www/static/;
expires 1d; # 可选:缓存一天
}
# 动态请求:反向代理到后端 Python 服务
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
注意:为了不与其他配置冲突,建议临时将其他所有监听 80 的 server 块移走或注释掉。
四、测试动静分离效果
1. 测试静态资源(Nginx 直接返回)
curl http://10.0.0.19/static/index.html
# 应显示 "<h1>This is static page served by Nginx</h1>"
curl http://10.0.0.19/static/style.css
# 应显示 CSS 内容
curl -I http://10.0.0.19/static/pic.jpg
# 注意响应头中应有 Nginx 特征,以及缓存控制(Cache-Control)
2. 测试动态请求(反向代理到 Python)
curl http://10.0.0.19/
# 应显示 "<h1>Dynamic response from backend (Python HTTP server)</h1>"
五、清理(实验完成后)
pkill -f "python3 -m http.server" # 或 pkill -f "python3 /tmp/app.py"
rm -f /etc/nginx/conf.d/reverse_proxy.conf
# 恢复原来的配置
mv /etc/nginx/conf.d/backup/*.conf /etc/nginx/conf.d/ 2>/dev/null
nginx -t && systemctl reload nginx
完成nginx四层代理实践,代理mysql和redis
一、大前提:检查 Nginx 是否支持 stream 模块
stream 模块不是所有 Nginx 版本都默认包含的,很多发行版需要单独安装或编译。
nginx -V 2>&1 | grep -o with-stream

有输出(显示 with-stream):说明已支持,可直接进入配置。
无输出:说明不支持,请执行以下命令安装:
apt install -y nginx-extras # Ubuntu 下带 stream 模块的版本
systemctl restart nginx
安装后再执行 nginx -V | grep stream 验证。
二、准备后端服务(在同一台机器模拟)
为了能立刻验证代理效果,我们在 Ubuntu 上同时启动 MySQL 和 Redis 服务。
安装 MySQL 和 Redis
apt install -y mysql-server redis-server
systemctl start mysql redis-server
systemctl enable mysql redis-server

创建测试数据
MySQL:
mysql -e "CREATE USER 'test'@'%' IDENTIFIED BY 'test123'; GRANT ALL PRIVILEGES ON *.* TO 'test'@'%'; FLUSH PRIVILEGES;"
Redis:
redis-cli set test_key "Hello from Redis"
验证后端服务正常:
mysql -utest -ptest123 -e "SELECT 'MySQL OK' as status"
redis-cli get test_key
三、配置 Nginx stream 模块代理 MySQL 和 Redis
修改主配置文件 /etc/nginx/nginx.conf,把 stream 块加在 http {} 外面
打开主配置文件:vim /etc/nginx/nginx.conf
在文件末尾,http {} 块的外面,添加 stream 配置(完整如下):

3. 检查配置并重启 Nginx
nginx -t
systemctl reload nginx
关键说明:
stream {} 是 Nginx 的四层(TCP/UDP)代理模块,和 http {} (七层 HTTP 代理)是同级的,不能嵌套在 http 里,也不能放在 conf.d/ 里(因为 conf.d/*.conf 默认是被 http 块包含的)。
检查监听端口:
四、验证代理效果
1. 验证 MySQL 代
通过代理连接 MySQL(端口 3307):

2. 验证 Redis 代理
通过代理连接 Redis(端口 10000):
3. 验证代理对故障的处理(测试 max_fails)
停止 MySQL 服务:
systemctl stop mysql
连续 3 次请求代理:
mysql -utest -ptest123 -h 127.0.0.1 -P 3307 -e "SELECT 1" # 第一次,失败
mysql -utest -ptest123 -h 127.0.0.1 -P 3307 -e "SELECT 1" # 第二次,失败
mysql -utest -ptest123 -h 127.0.0.1 -P 3307 -e "SELECT 1" # 第三次,失败
第 3 次失败后,Nginx 将后端标记为不可用。恢复 MySQL 服务:
systemctl start mysql
注意:fail_timeout=30s 表示 30 秒后 Nginx 会尝试重新激活后端服务器,而不是永久剔除。
# 等待 30 秒后再测试
sleep 30
mysql -utest -ptest123 -h 127.0.0.1 -P 3307 -e "SELECT 'Recovered' as msg"

这时代理恢复正常。
关键算法说明:
-
least_conn:优先将请求分发到当前活跃连接数最少的后端。 -
hash $remote_addr consistent:根据客户端 IP 进行一致性哈希,保证同一客户端的请求始终落入同一后端(对 Redis 的 pipeline 和事务很重要)。 -
backup:标记为备用节点,仅当所有主节点都不可用时才启用。
负载均衡算法完整列表(用于 upstream 块)。
五、清理(实验完成后)
rm -f /etc/nginx/conf.d/stream.conf
nginx -t && systemctl reload nginx
如果不需要 MySQL 和 Redis,可以停止并卸载:
systemctl stop mysql redis-server
apt remove -y mysql-server redis-server
更多推荐



所有评论(0)