Nginx 反向代理

正向代理、反向代理是运维工作中非常容易混淆的概念,也是 Nginx 核心能力之一。Nginx 依托不同模块,既可以实现简单的 HTTP 转发、动静分离,也能实现后端集群负载均衡、缓存加速,是企业 Web 架构里非常常用的接入层组件。

正向代理 vs 反向代理

  • 正向代理 :代理代表客户端去访问服务端。客户端需要手动配置代理地址,服务器感知到的访问来源是代理服务器,不知道真实客户端。典型场景:翻墙代理。
  • 反向代理 :代理代表后端服务器集群接收客户端请求。客户端不需要做任何配置,只访问反向代理地址,感知不到后端真实服务器,由代理把请求转发给后端节点。典型场景:网站入口、负载均衡。

Nginx 除了本身作为高性能 Web 服务,还可以把自身无法处理的请求,按照协议转发给其他服务,依靠下面几个核心模块实现:

  1. ngx_http_proxy_module:HTTP 协议反向代理,最常用
  2. ngx_http_upstream_module:定义后端服务器组,给 proxy_pass、fastcgi_pass 等引用,实现负载均衡
  3. ngx_stream_proxy_module:TCP 四层代理,做端口转发
  4. ngx_http_fastcgi_module:FastCGI 协议代理,转发 PHP 请求
  5. ngx_http_uwsgi_module:uWSGI 协议代理,转发 Python Web 项目请求

同构代理:直接使用 HTTP/TCP 协议转发,后端本身就是 Web 服务,不需要额外协议解析,如静态页面、接口服务。 异构代理:请求需要后端程序解析处理,不能直接返回文件,例如 PHP、Python 动态程序。

1.1 HTTP 反向代理

官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html

1.1.1 反向代理常用配置参数

参数 说明
proxy_pass 核心指令,指定转发目标,可以是 IP: 端口、域名,或者 upstream 后端组
proxy_hide_header field 隐藏后端返回给客户端的响应头
proxy_pass_header field 透传后端默认不对外发送的响应头
proxy_set_header 修改 / 新增请求头,常用X-Forwarded-For传递客户端真实 IP
proxy_connect_timeout Nginx 和后端建立连接超时,默认 60s
proxy_read_timeout 连接成功后,读取后端响应超时,默认 60s
proxy_send_timeout 向后端发送请求数据的超时,默认 60s
proxy_http_version 设置代理使用的 HTTP 版本,默认 1.0
proxy_ignore_client_abort 客户端断开连接时,Nginx 是否继续等待后端返回,off 则直接终止,记录 499
1. proxy_pass 基础示例

环境准备:

  • RS3:172.25.254.11

  • RS4:172.25.254.12

    RS3

    [root@RS3 ~]# echo 172.25.254.11-RS3 > /var/www/html/index.html

    RS4

    [root@RS4 ~]# echo 172.25.254.12-RS4 > /var/www/html/index.html
    [root@RS4 ~]# mkdir /var/www/html/web
    [root@RS4 ~]# echo 172.25.254.12-RS4-web > /var/www/html/web/index.html

    Nginx主机测试连通性

    [root@Nginx ~]# curl 172.25.254.11
    172.25.254.11-RS3
    [root@Nginx ~]# curl 172.25.254.12
    172.25.254.12-RS4

Nginx 配置 /usr/local/nginx/conf/conf.d/vhost.conf

复制代码
server {
    listen 80;
    server_name www.doubledragon.org;
    root /webdata/nginx/doubledragon.org;

    location / {
        proxy_pass http://172.25.254.11:80;
    }
    location /web {
        proxy_pass http://172.25.254.12:80;
    }
}

重载配置:

复制代码
[root@Nginx ~]# nginx -s reload

访问测试:

复制代码
[root@Nginx ~]# curl www.doubledragon.org
172.25.254.11-RS3
[root@Nginx ~]# curl www.doubledragon.org/web/
172.25.254.12-RS4-web
2. proxy_hide_header 隐藏响应头示例

不加配置前,curl -v 可以看到后端返回的ETag头信息:

复制代码
< ETag: "16-64de788fdf02b"

修改配置,隐藏 ETag:

复制代码
location /web {
    proxy_pass http://172.25.254.12:80;
    proxy_hide_header ETag;
}

再次curl -v访问,ETag 头部不再返回给客户端,常用于安全脱敏。

3. proxy_pass_header 透传响应头示例

默认 Nginx 不会透传后端Server头部,我们使用proxy_pass_header开启透传:

复制代码
location / {
    proxy_pass http://172.25.254.11:80;
    proxy_pass_header server;
}

访问后可以看到后端真实 Server 版本:

复制代码
< Server: Apache/2.4.57 (Red Hat Enterprise Linux)
4. proxy_set_header 传递真实客户端 IP

后端服务器默认拿到的源 IP 是 Nginx 代理 IP,需要设置X-Forwarded-For传递真实客户端 IP。

修改 RS3 的 httpd 日志格式,增加 X-Forwarded-For 字段:

复制代码
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Forwarded-For}i\"" combined

重启 httpd。

Nginx 配置:

复制代码
location / {
    proxy_pass http://172.25.254.11:80;
    proxy_pass_header server;
    proxy_set_header X-Forwarded-For $remote_addr;
}

访问后查看 RS3 日志,即可拿到客户端真实 IP。

1.1.2 实战案例:反向代理动静分离

动静分离是生产常用架构:静态资源(html、图片、js、css)交给静态服务器;PHP 动态请求转发给后端 PHP 服务。

环境准备:RS3 安装 httpd+php

复制代码
[root@RS3 ~]# dnf install php -y
[root@RS3 ~]# systemctl restart httpd
[root@RS3 ~]# vim /var/www/html/index.php

php 页面内容:

复制代码
<?php
    echo "<h2>172.25.254.11</h2>";
    phpinfo();
?>

Nginx 配置:

复制代码
server {
    listen 80;
    server_name www.doubledragon.org;
    root /webdata/nginx/doubledragon.org;

    location / {
        proxy_pass http://172.25.254.12:80;
    }
    location ~* \.(php|js)$ {
        proxy_pass http://172.25.254.11:80;
    }
}

重载 Nginx,浏览器访问www.doubledragon.org/index.php测试。

1.1.3 反向代理缓存 proxy_cache

代理缓存可以把后端返回的内容缓存到 Nginx 本地,后续相同请求直接由 Nginx 返回,大幅降低后端压力、提升响应速度,默认关闭。

核心缓存参数
  • proxy_cache_path:http 块中定义缓存存储路径、目录层级、内存 key 空间、过期、磁盘上限
  • proxy_cache:location 中启用缓存,引用上面定义的 zone
  • proxy_cache_key:缓存的主键,默认$scheme$proxy_host$request_uri
  • proxy_cache_valid:针对不同状态码设置缓存时长
  • proxy_cache_use_stale:后端异常时,允许返回过期缓存兜底
  • proxy_cache_methods:指定哪些 HTTP 方法可以缓存,GET、HEAD 默认缓存

proxy_cache_path示例:

复制代码
proxy_cache_path /usr/local/nginx/proxy_cache
levels=1:2:2
keys_zone=proxycache:20m
inactive=120s
max_size=1g;
  • levels=1:2:2:三级目录结构,分散缓存文件,避免单目录文件过多
  • keys_zone=proxycache:20m:内存存放缓存 key 和元数据
  • inactive=120s:120s 没有访问则缓存失效清理
  • max_size=1g:缓存磁盘最大容量
1. 无缓存压测

使用 ab 压测动态 PHP 页面,动态页面每次都请求后端 PHP,并发高时大量失败:

复制代码
ab -n 10000 -c 50 www.doubledragon.org/index.php

压测结果:大量 Failed requests,QPS 低,等待耗时高。

2. 开启缓存加速
  1. 主配置 nginx.conf 的 http 段添加 proxy_cache_path

  2. vhost.conf 在 php 的 location 启用缓存

    location ~* .(php|js) { proxy_pass http://172.25.254.11:80; proxy_cache proxycache; proxy_cache_key request_uri;
    proxy_cache_valid 200 302 301 10m;
    proxy_cache_valid any 1m;
    }

重启 Nginx,再次压测。

3. 验证缓存效果

开启缓存后,同样压测参数:请求全部成功,QPS 大幅上涨,响应时间显著降低。 查看缓存目录:

复制代码
tree /usr/local/nginx/proxy_cache

可以看到 Nginx 自动生成缓存目录与缓存实体文件。

1.2 HTTP 反向代理负载均衡(upstream)

上面的 proxy_pass 只能转发到单台后端;ngx_http_upstream_module可以定义后端服务器组,实现多节点负载均衡、故障摘除、备份节点、多种调度算法。 官方文档:https://nginx.org/en/docs/http/ngx_http_upstream_module.html

1.2.1 upstream 参数说明

复制代码
upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server backup1.example.com backup;
}

server 后面支持的参数:

  • weight:权重,默认 1,权重越高分配请求越多
  • max_conns:当前节点最大并发连接,0 代表无限制
  • max_fails:连续失败多少次,标记节点不可用,默认 1
  • fail_timeout:节点标记失败后,多久之后重新探测,默认 10s
  • backup:备份节点,全部主节点故障才启用
  • down:标记永久下线,平滑维护
  • ip_hash:源 IP 哈希,会话保持,同一个客户端 IP 固定访问一台后端
  • least_conn:最少连接算法,优先分给当前连接数少的节点
  • hash $key consistent:一致性哈希,适合缓存集群

1.2.2 负载均衡完整示例

编辑负载均衡配置文件 loadbalance.conf

复制代码
upstream webserver {
    server 172.25.254.11:80 weight=1 fail_timeout=15s max_fails=3;
    server 172.25.254.12:80 weight=1 fail_timeout=15s max_fails=3;
    server 172.25.254.10:8888 backup;
}
server {
    listen 80;
    server_name www.doubledragon.org;

    location ~ / {
        proxy_pass http://webserver;
    }
}

重启 Nginx 测试:

复制代码
curl www.doubledragon.org

轮流返回 RS3、RS4 内容,实现轮询负载均衡;RS3、RS4 全部宕机后,自动切换到 backup 备份节点。

ip_hash是基于源 IP 做会话保持,当大量用户出口 NAT 时会有问题;基于 Cookie 里的 sessionid 做 hash,是更精准的会话绑定方案:

复制代码
upstream webserver {
    hash $cookie_sessionid consistent;
    server 172.25.254.11:80;
    server 172.25.254.12:80;
}

用户 Cookie 里 sessionid 不变,则始终调度到同一台后端,适合需要会话保持的业务。

相关推荐
程序员-Benothing19 小时前
Linux安全加固指南:账号、权限、服务、审计基线
linux·运维·安全
Mininglamp_271819 小时前
接口调用 vs 屏幕理解:两种 GUI 自动化架构的技术取舍
运维·架构·自动化
爱喝水的鱼丶21 小时前
SAP-ABAP:ECC→S/4HANA ABAP 迁移升级指南——程序改造、语法兼容与性能优化 导语
运维·开发语言·性能优化·sap·abap·经验交流·开发交流
木子欢儿21 小时前
openconnect Linux客户端安装 以及开机自启和登录
linux·运维·服务器
..Dauntless..1 天前
【Linux】文件系统(一)
linux·运维·服务器
天空属于哈夫克31 天前
企业微信API二次开发 赋能私域运营自动化
运维·自动化·企业微信
天远API1 天前
零信任架构实战:基于天远运营商二要素V即时版构建自动化分时租赁出行会员身份一致性审核网关
运维·人工智能·架构·自动化
极光通讯1 天前
液冷服务器对内存和SSD的适配要求:高密度部署下的散热与信号完整性
运维·服务器
2501_937767161 天前
面向设计 / 研发部门:终端文件统一归档 + 服务器定时备份实践
运维·安全
阿里云云原生1 天前
Personal Agent 观察:拆解全天候运行的技术挑战
云原生·agent