Nginx反向代理与负载均衡全解析

Nginx反向代理与负载均衡全解析

在服务器架构设计中,Nginx凭借轻量、高性能的特性,成为反向代理和负载均衡的核心工具,同时能高效实现动静分离,大幅提升服务处理能力。本文将从基础概念出发,结合实战案例,详细拆解Nginx的核心应用。

一、代理基础:正向代理 vs 反向代理

要理解Nginx的作用,首先需明确"代理"的本质------作为"中间渠道"连接两个角色(被代理方与目标方),根据代理对象的不同,分为正向代理反向代理

1.1 什么是代理?

代理是"中间媒介",核心是"代为交互":

  • 被代理角色:需要通过代理完成操作的一方(如客户端、后端服务器);
  • 目标角色:被代理角色最终要访问的对象(如目标网站、客户端);
  • 类比:专卖店是"品牌厂家"的代理,用户(目标)通过专卖店(代理)购买厂家(被代理)的商品。

1.2 正向代理:代理客户端

正向代理的代理对象是客户端,用于解决客户端无法直接访问目标服务器的问题(如跨地域、权限限制)。

核心特点:
  • 客户端明确知道目标服务器地址(如用户知道要访问某国外网站);

  • 目标服务器仅知道请求来自代理服务器,无法识别真实客户端(隐藏客户端信息);

  • 典型场景:科学上网(客户端通过代理服务器访问国外网站)、企业内网客户端通过代理访问外网。

1.3 反向代理:代理后端服务器

反向代理的代理对象是后端服务器,用于服务器集群的分布式部署,隐藏后端服务器细节,统一对外提供服务。

核心特点:
  • 客户端不知道真实后端服务器地址,仅知道反向代理服务器(如用户访问www.xxx.com,实际请求由Nginx转发到后端多台服务器);

  • 反向代理负责"分发请求"到后端集群,提升并发能力和可用性;

  • 典型场景:网站后端集群(Nginx作为入口,转发请求到多台Tomcat/Httpd服务器)。

1.4 正向代理与反向代理对比

维度 正向代理 反向代理
代理对象 客户端 后端服务器
客户端感知 知道目标服务器地址 仅知道代理服务器地址
核心作用 突破访问限制(如跨地域) 负载均衡、隐藏后端服务
典型场景 科学上网、内网访问外网 网站集群入口、动静分离

1.5 生产场景:正反向代理结合

实际架构中,正反向代理常配合使用:

  1. 客户端通过正向代理(如企业代理服务器)访问外网;

  2. 外网请求到达反向代理(如Nginx);

  3. 反向代理将请求转发到后端真实业务服务器集群。

二、Nginx核心能力:反向代理、负载均衡与动静分离

Nginx的核心价值通过三大模块实现:Http Proxy(反向代理)、upstream(负载均衡)、静态资源处理(动静分离)。

2.1 反向代理:基于Http Proxy模块

Http Proxy模块是Nginx实现反向代理的核心,最常用指令为proxy_passproxy_cache

1. 核心指令说明
指令 作用
proxy_pass 指定后端服务器地址(如proxy_pass http://webserver;,转发请求到webserver集群)
proxy_cache 开启代理缓存(减少重复请求到后端,提升性能),需集成第三方模块ngx_cache_purge清除指定URL缓存
2. 集成ngx_cache_purge(清除缓存)

proxy_cache默认不支持"精准清除缓存",需在Nginx安装时集成ngx_cache_purge模块:

bash 复制代码
# 编译安装时添加模块(路径需替换为实际模块路径)
./configure --add-module=../ngx_cache_purge-1.0  # 其他编译参数(如--prefix=/usr/local/nginx)
make && make install

2.2 负载均衡:基于upstream模块

upstream模块用于定义后端服务器集群,Nginx通过该模块实现请求的"合理分发",支持多种负载均衡策略,需在nginx.confhttp段内配置。

2.2.1 常用负载均衡策略

Nginx默认支持两种核心策略,可根据业务需求选择:

1. weight轮询(默认策略)
  • 原理 :请求按顺序逐一分配到后端服务器,支持通过weight设置权重(权重越高,分配到的请求越多);
  • 自愈能力:后端服务器宕机时,Nginx会自动剔除该服务器,不影响整体服务;
  • 适用场景:后端服务器硬件配置不同(如高配服务器设置更高权重,承担更多请求)。
2. ip_hash
  • 原理:根据客户端IP的Hash值分配请求,固定IP的客户端始终访问同一台后端服务器;
  • 核心优势:解决集群中"Session共享"问题(如用户登录状态保存在某台服务器,后续请求仍定向到该服务器);
  • 注意事项 :移除故障服务器时,需用down标记(而非直接删除配置),避免Hash算法重新计算导致Session失效。
2.2.2 负载均衡实战案例

以下案例基于3台主机搭建,实现Nginx负载均衡到两台Httpd服务器。

1. 环境准备
主机名 IP地址 安装服务 作用
Nginx 192.168.100.10 Nginx 反向代理+负载均衡入口
Rs1 192.168.100.20 Httpd 后端静态服务器1
Rs2 192.168.100.30 Httpd 后端静态服务器2

前置操作:3台主机均需关闭防火墙和SELinux,确保网络互通,并配置好Yum仓库:

java 复制代码
// 关闭防火墙
[root@nginx ~]# systemctl stop firewalld && systemctl disable firewalld
[root@rs1 ~]# systemctl stop firewalld && systemctl disable firewalld
[root@rs2 ~]# systemctl stop firewalld && systemctl disable firewalld

// 关闭SELinux
[root@nginx ~]# setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@rs1 ~]# setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@rs2 ~]# setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
2. 部署后端Httpd服务器(Rs1、Rs2)

两台服务器操作一致,主要是安装Httpd并创建测试页面,用于后续验证负载均衡效果:

java 复制代码
// 1. 安装Httpd(Rs1执行)
[root@rs1 ~]# yum -y install httpd

// 2. 创建测试页面(Rs1写"I am RS1")
[root@rs1 ~]# echo "I am RS1" > /var/www/html/index.html

// 3. 启动Httpd并设置开机自启
[root@rs1 ~]# systemctl restart httpd && systemctl enable httpd



// 1. 安装Httpd(Rs2执行)
[root@rs2 ~]# yum -y install httpd

// 2. 创建测试页面(Rs2写"I am RS2")
[root@rs2 ~]# echo "I am RS2" > /var/www/html/index.html

// 3. 启动Httpd并设置开机自启
[root@rs2 ~]# systemctl restart httpd && systemctl enable httpd
3. 配置Nginx负载均衡

修改Nginx主配置文件/usr/local/nginx/conf/nginx.conf,通过upstream定义后端集群,并用proxy_pass转发请求:

案例1:默认weight轮询(权重1:1)
bash 复制代码
http {
    # 1. 定义后端服务器集群(命名为webserver)
    upstream webserver {
        server 192.168.100.20;  # Rs1,默认权重1
        server 192.168.100.30;  # Rs2,默认权重1
    }

    # 2. 配置虚拟主机,转发请求到集群
    server {
        listen 80;  # 监听80端口
        server_name localhost;  # 域名(生产环境替换为实际域名,如www.xxx.com)

        location / {
            proxy_pass http://webserver;  # 转发所有请求到webserver集群
        }
    }
}

测试验证

  1. 检查配置文件语法并重载Nginx:

    java 复制代码
    [root@nginx ~]# nginx -t  // 语法检查,显示"syntax is ok"则正常
    nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
    
    [root@nginx ~]# nginx -s reload  // 重载配置


案例2:自定义权重(Rs1权重3: Rs2权重1)

若Rs1硬件配置更高,可设置weight=3,让其承担3倍请求:

bash 复制代码
http {
    upstream webserver {
        server 192.168.100.20 weight=3;  # 权重3,承担3/4请求
        server 192.168.100.30;           # 权重1,承担1/4请求
    }

    server {
        listen 80;
        server_name localhost;

        location / {
            proxy_pass http://webserver;
        }
    }
}
  1. 重载 Nginx 配置:

    java 复制代码
    [root@nginx ~]# nginx -t
    [root@nginx ~]# nginx -s reload
案例3:指定后端服务器端口(Rs1用8080端口)

若后端服务器端口非默认80(如Rs1改为8080),需在upstream中明确指定端口:

  1. 修改Rs1的Httpd端口为8080:

    java 复制代码
    [root@rs1 ~]# vim /etc/httpd/conf/httpd.conf
    // 将文件中"Listen 80"改为"Listen 8080"
    [root@rs1 ~]# systemctl restart httpd
  2. 调整Nginx配置:

    bash 复制代码
    http {
        upstream webserver {
            server 192.168.100.20:8080;  # 明确指定Rs1的8080端口
            server 192.168.100.30;       # Rs2仍用80端口
        }
    
        server {
            listen 80;
            server_name localhost;
    
            location / {
                proxy_pass http://webserver;
            }
        }
    }
  3. 重载Nginx并测试:

java 复制代码
[root@nginx ~]# nginx -t
[root@nginx ~]# nginx -s reload
案例4:ip_hash策略(解决Session共享)

如果在集群中的某台服务器出现故障,我们想要从nginx的集群配置中移除掉,我们不可以直接的将那一行删掉,比如server 192.168.100.10:8080 weight=2;删掉,如果直接删掉会导致nginx的hash算法重新计算,那么用户的会话或者说缓存都会失效掉,所以这里如果不用这台服务器,直接比较为down即可,也就是 server 192.168.100.10:8080 down

若后端是动态服务(如Tomcat),需保证同一用户的请求定向到同一台服务器,避免Session失效:

bash 复制代码
http {
    upstream webserver {
        ip_hash;  # 开启ip_hash策略(需放在server列表前)
        server 192.168.100.20;
        server 192.168.100.30;
        # 若某台服务器故障,用down标记(而非删除),避免Hash重算
        # server 192.168.100.40 down;  # 故障服务器标记为down
    }

    server {
        listen 80;
        server_name localhost;

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

测试验证

  1. 重载 Nginx 配置:

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

2.3 动静分离:静态资源Nginx直返,动态请求转发

动静分离是Nginx的核心优化手段------静态资源(HTML、CSS、JS、图片)由Nginx直接读取返回,动态资源(如Java接口、PHP脚本)转发到后端服务(如Tomcat、PHP-FPM),减少后端服务器压力。

nginx实现动静分离,其实就是在反向代理的时候,如果是静态资源,就直接从nginx发布的路径去读取,而不需要从后台服务器获取了。

但是要注意,这种情况下需要保证后端跟前端的程序保持一致,可以使用Rsync做服务端自动同步或者使用NFS、MFS分布式共享存储。

核心原理:
  • 静态资源:Nginx通过rootalias指定本地路径,直接读取文件返回(无需转发到后端);
  • 动态资源:通过location匹配动态路径(如/test),用proxy_pass转发到后端动态服务(如Tomcat)。
动静分离实战案例(Nginx + Httpd + Tomcat)

基于前文环境,新增一台Tomcat服务器(IP:192.168.100.30,端口8080),实现:

  • 静态请求(/):转发到Httpd集群(Rs1、Rs2);
  • 动态请求(/test):转发到Tomcat。
1. 部署Tomcat

步骤省略

验证Tomcat :客户端访问http://192.168.100.30:8080,能看到Tomcat默认页面即部署成功。

2. 配置Nginx动静分离

修改nginx.conf,新增upstream static(静态集群)和upstream tomcat(动态服务),并通过location匹配路由:

bash 复制代码
http {
    # 1. 静态资源集群(Httpd服务器)
    upstream static {
        server 192.168.100.20;
        server 192.168.100.30;  
    }

    # 2. 动态服务(Tomcat)
    upstream tomcat {
        server 192.168.100.30:8080;  # Tomcat的8080端口
    }

    server {
        listen 80;
        server_name localhost;

        # 3. 静态请求:匹配根路径"/",转发到static集群
        location / {
            proxy_pass http://static;
        }

        # 4. 动态请求:匹配"/test"路径,转发到Tomcat
        location /test {
            proxy_pass http://tomcat;
            # 可选:添加代理请求头,让Tomcat获取真实客户端IP
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}
3. 测试验证
java 复制代码
[root@nginx ~]# nginx -t
[root@nginx ~]# nginx -s reload


相关推荐
草莓熊Lotso4 小时前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
历程里程碑4 小时前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
七夜zippoe13 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy64814 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满14 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
主机哥哥15 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Harvey90315 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技16 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀16 小时前
Linux环境变量
linux·运维·服务器