Nginx反向代理与负载均衡全解析
Nginx反向代理与负载均衡全解析
在服务器架构设计中,Nginx凭借轻量、高性能的特性,成为反向代理和负载均衡的核心工具,同时能高效实现动静分离,大幅提升服务处理能力。本文将从基础概念出发,结合实战案例,详细拆解Nginx的核心应用。
一、代理基础:正向代理 vs 反向代理
要理解Nginx的作用,首先需明确“代理”的本质——作为“中间渠道”连接两个角色(被代理方与目标方),根据代理对象的不同,分为正向代理和反向代理。
1.1 什么是代理?
代理是“中间媒介”,核心是“代为交互”:
- 被代理角色:需要通过代理完成操作的一方(如客户端、后端服务器);
- 目标角色:被代理角色最终要访问的对象(如目标网站、客户端);
- 类比:专卖店是“品牌厂家”的代理,用户(目标)通过专卖店(代理)购买厂家(被代理)的商品。
1.2 正向代理:代理客户端
正向代理的代理对象是客户端,用于解决客户端无法直接访问目标服务器的问题(如跨地域、权限限制)。
核心特点:
-
客户端明确知道目标服务器地址(如用户知道要访问某国外网站);
-
目标服务器仅知道请求来自代理服务器,无法识别真实客户端(隐藏客户端信息);
-
典型场景:科学上网(客户端通过代理服务器访问国外网站)、企业内网客户端通过代理访问外网。
1.3 反向代理:代理后端服务器
反向代理的代理对象是后端服务器,用于服务器集群的分布式部署,隐藏后端服务器细节,统一对外提供服务。
核心特点:
-
客户端不知道真实后端服务器地址,仅知道反向代理服务器(如用户访问
www.xxx.com
,实际请求由Nginx转发到后端多台服务器); -
反向代理负责“分发请求”到后端集群,提升并发能力和可用性;
-
典型场景:网站后端集群(Nginx作为入口,转发请求到多台Tomcat/Httpd服务器)。
1.4 正向代理与反向代理对比
维度 | 正向代理 | 反向代理 |
---|---|---|
代理对象 | 客户端 | 后端服务器 |
客户端感知 | 知道目标服务器地址 | 仅知道代理服务器地址 |
核心作用 | 突破访问限制(如跨地域) | 负载均衡、隐藏后端服务 |
典型场景 | 科学上网、内网访问外网 | 网站集群入口、动静分离 |
1.5 生产场景:正反向代理结合
实际架构中,正反向代理常配合使用:
-
客户端通过正向代理(如企业代理服务器)访问外网;
-
外网请求到达反向代理(如Nginx);
-
反向代理将请求转发到后端真实业务服务器集群。
二、Nginx核心能力:反向代理、负载均衡与动静分离
Nginx的核心价值通过三大模块实现:Http Proxy
(反向代理)、upstream
(负载均衡)、静态资源处理(动静分离)。
2.1 反向代理:基于Http Proxy模块
Http Proxy
模块是Nginx实现反向代理的核心,最常用指令为proxy_pass
和proxy_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
模块:
# 编译安装时添加模块(路径需替换为实际模块路径)
./configure --add-module=../ngx_cache_purge-1.0 # 其他编译参数(如--prefix=/usr/local/nginx)
make && make install
2.2 负载均衡:基于upstream模块
upstream
模块用于定义后端服务器集群,Nginx通过该模块实现请求的“合理分发”,支持多种负载均衡策略,需在nginx.conf
的http
段内配置。
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仓库:
// 关闭防火墙
[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并创建测试页面,用于后续验证负载均衡效果:
// 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)
http {# 1. 定义后端服务器集群(命名为webserver)upstream webserver {server 192.168.100.20; # Rs1,默认权重1server 192.168.100.30; # Rs2,默认权重1}# 2. 配置虚拟主机,转发请求到集群server {listen 80; # 监听80端口server_name localhost; # 域名(生产环境替换为实际域名,如www.xxx.com)location / {proxy_pass http://webserver; # 转发所有请求到webserver集群}}
}
测试验证:
-
检查配置文件语法并重载Nginx:
[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倍请求:
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;}}
}
-
重载 Nginx 配置:
[root@nginx ~]# nginx -t [root@nginx ~]# nginx -s reload
案例3:指定后端服务器端口(Rs1用8080端口)
若后端服务器端口非默认80(如Rs1改为8080),需在upstream
中明确指定端口:
-
修改Rs1的Httpd端口为8080:
[root@rs1 ~]# vim /etc/httpd/conf/httpd.conf // 将文件中“Listen 80”改为“Listen 8080” [root@rs1 ~]# systemctl restart httpd
-
调整Nginx配置:
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;}} }
-
重载Nginx并测试:
[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失效:
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;}}
}
测试验证:
-
重载 Nginx 配置:
[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通过
root
或alias
指定本地路径,直接读取文件返回(无需转发到后端); - 动态资源:通过
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
匹配路由:
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”路径,转发到Tomcatlocation /test {proxy_pass http://tomcat;# 可选:添加代理请求头,让Tomcat获取真实客户端IPproxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
}
3. 测试验证
[root@nginx ~]# nginx -t
[root@nginx ~]# nginx -s reload