Nginx反向代理及负载均衡

Nginx反向代理及负载均衡

  • 实验环境

    • 四台虚拟机

      IP 说明
      172.25.254.101 nginx负载均衡器
      172.25.254.102 客户端
      172.25.254.103 web服务器1
      172.25.254.104 web服务器2

一、nginx反向代理

1.1 nginx反向代理原理

​ 反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。

Nginx 反向代理的原理是将客户端的请求转发到后端真实服务器,并将后端服务器的响应返回给客户端,同时对客户端隐藏后端服务器的真实信息。以下是其详细原理:

  • 客户端发起请求:客户端向 Nginx 反向代理服务器发送请求,请求中包含目标 URL 等信息。
  • Nginx 接收请求:Nginx 监听在特定的端口上,接收客户端的请求。它会根据配置文件中的规则来判断如何处理该请求。
  • 请求匹配与转发:Nginx 根据配置的虚拟主机、域名、URL 路径等规则,将请求匹配到对应的后端服务器组。然后,Nginx 会选择一台后端服务器,并将请求转发给它。
  • 后端服务器处理请求:后端服务器接收到 Nginx 转发的请求后,进行相应的处理,如查询数据库、执行应用程序逻辑等,生成响应数据。
  • Nginx 接收后端服务器响应:后端服务器将响应数据发送给 Nginx。
  • Nginx 将响应返回给客户端:Nginx 接收后端服务器的响应后,根据配置进行一些额外的处理,如添加响应头、缓存响应等,然后将响应数据返回给客户端。

通过以上过程,Nginx 作为反向代理服务器,充当了客户端和后端服务器之间的中间桥梁,实现了对后端服务器的负载均衡、缓存加速、安全防护等功能,同时提高了系统的性能和可扩展性。

1.2 nginx反向代理配置

  • 安装nginx

    复制代码
    ## 在nginx负载均衡器和服务器三台机器上分别安装nginx
    [root@Rocky ~]# dnf install nginx -y
  • 配置用于测试的Web服务(以下操作在两台web服务器)

    复制代码
    ## 创建日志文件目录
    [root@Rocky ~]# mkdir -p /usr/share/nginx/html/{www,bbs}/logs
    [root@Rocky ~]# cd /etc/nginx/conf.d/
    [root@Rocky conf.d]# vim vhost.conf
    [root@Rocky conf.d]# cat vhost.conf
    server {
    		listen 80;
    		server_name bbs.yunjisuan.com;
    		location / {
    				root /usr/share/nginx/html/bbs;
    				index index.html index.htm;
    		}
    		access_log /usr/share/nginx/html/bbs/logs/access_bbs.log main;
    }
    server {
    		listen 80;
    		server_name www.yunjisuan.com;
    		location / {
    				root /usr/share/nginx/html/www;
    				index index.html index.htm;
    		}
    		access_log /usr/share/nginx/html/www/logs/access_www.log main;
    }
    ## 检查是否有语法错误
    [root@Rocky conf.d]# nginx -t
    [root@Rocky conf.d]# echo "`hostname -I ` . www" > /usr/share/nginx/html/www/index.html
    [root@Rocky conf.d]# echo "`hostname -I ` . bbs" > /usr/share/nginx/html/bbs/index.html
    
    ## 启动服务测试
    [root@Rocky conf.d]# systemctl start nginx
    [root@Rocky ~]# curl -H host:bbs.yunjisuan.com 172.25.254.103
    172.25.254.103 . bbs
    [root@Rocky ~]# curl -H host:bbs.yunjisuan.com 172.25.254.104
    172.25.254.104 . bbs
    [root@Rocky ~]# curl -H host:www.yunjisuan.com 172.25.254.104
    172.25.254.104 . www
    [root@Rocky ~]# curl -H host:www.yunjisuan.com 172.25.254.103
    172.25.254.103 . www

二、nginx负载均衡

Nginx 通过反向代理实现负载均衡,客户端的请求先到达 Nginx,Nginx 依据配置规则,把请求转发给不同的后端服务器,并将处理结果返回给客户端。其采用多进程 + 异步非阻塞 I/O 事件模型,能高效处理大量并发请求。

2.1 nginx模块

​ Nginx的负载均衡功能依赖于ngx_http_upsteam_module模块,所支持的代理方式包括proxy_pass,fastcgi_pass,memcached_pass等,新版Nginx软件支持的方式有所增加。本文主要讲解proxy_pass代理方式。ngx_http_upstream_module模块允许Nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应Upstream组的名字上,具体写法为"proxy_pass http:// www_server_pools",其中www_server_pools就是一个Upstream节点服务器组名字。ngx_http_upstream_module模块官方地址为:http://nginx.org/en/docs/http/ngx_http_upstream_module.html。

  • 示例1:基本的upstream配置案例

    复制代码
    upstream www_server_pools {
    #upstream是关键字必须有,后面的www_server_pools为一个Upstream集群组的名字,可以自己起名,调用时就用这个名字
    	server 172.25.254.223:80 weight=5;
    	server 172.25.254.224:80 weight=10;
    	server 172.25.254.225:80 weight=15;
    #server关键字是固定的,后面可以接域名(门户会用)或IP。如果不指定端口,默认是80端口。weight代表权重,数值越大被分配的请求越多,结尾有分号。
    }
  • 示例2:较完整的upstream配置案例

    复制代码
    upstream www_server_pools {
    	server 172.25.254.223; #这行标签和下行是等价的
    	server 172.25.254.224:80 weight=1 max_fails=1 fail_timeout=10s; #这行标签和上一行是等价的,此行多余的部分就是默认配置,不写也可以。
    	server 172.25.254.225:80 weight=1 max_fails=2 fail_timeout=20s backup;
    # server最后面可以加很多参数,具体参数作用看下文的表格
    }
  • 示例3:使用域名及socket的upstream配置案例

    复制代码
    upstream backend {
    	server backend1.example.com weight=5;
    	server backend2.example.com:8080; #域名加端口。转发到后端的指定端口上
    	server unix:/tmp/backend3; #指定socket文件
    	#提示:server后面如果接域名,需要内网有DNS服务器或者在负载均衡器的hosts文件做域名解析。
    	server 172.25.254.223;
    	server 172.25.254.224:8080;
    	server backup1.example.com:8080 backup;
    	#备份服务器,等上面指定的服务器都不可访问的时候会启动,backup的用法和Haproxy中用法一样
    	server backup2.example.com:8080 backup;
    }
  • upstream参数

    复制代码
    server 10.0.10.8:80 	负载均衡后面的RS配置,可以是IP或域名,如果端口不写,默认是80端口。高并发场景下, IP可换成域名,通过 DNS做负载均衡。
    weigth=1 	代表服务器的权重,默认值是1。权重数字越大表示接受的请求比例越大。
    max_fails=3		Nginx尝试连接后端主机失败的次数,这个值是配合
    proxy_next_upstream、fastcgi_next_upstream和memcached_next_upstream	这三个参数来使用的。当nginx接收后端服务器返回这三个参数定义的状态码时,会将这个请求转发给正常工作的后端服务器,例如404、502、503、 Max_fails的默认值是1 ;企业场景下建议2-3次。如京东1次,蓝汛10次,根据业务需求去配置
    fail_timeout=10s	在max_fails定义的失败次数后,距离下次检查的间隔时间,默认是10s ;如果max_fails是5 ,它就检测5次,如果5次都是502,那么,它就会根据fail_timeout的值,等待10s再去检查,还是只检查一次,如果持续502,在不重新加载 Nginx配置的情况下,每隔10s都只检查一次。常规业务2~3秒比较合理,比如京东3秒,蓝汛3秒,可根据业务需求去配置。
    backup	热备配置(RS节点的高可用),当前面激活的RS都失败后会自动启用热备RS这标志看这个服务器作为备份服务器,若主服务器全部宕机了,就会向它转发请求。注意:当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。
    down 	这标志着服务器永远不可用,这个参数可配合ip_hash使用;类似与注释。

2.1 常用模块调度算法

  • 轮询(roundrobin):按顺序依次将请求分发到后端服务器,从第一台开始,到最后一台后再回到第一台,循环进行,不考虑服务器性能差异和负载情况,均等分配请求。
  • 加权轮询(weight):在轮询基础上,为各后端服务器设置权重,权重代表服务器处理请求的能力。权重越高,被分配到请求的概率越大,按权重比例分配请求,用于后端服务器性能不均衡场景。
  • IP 哈希(ip_hash):对客户端 IP 地址进行哈希运算,通过哈希值与后端服务器列表映射,使同一客户端的请求始终发往同一台后端服务器,以维持客户端会话状态。
  • 最少连接数(least_conn):将请求分配给当前连接数最少的后端服务器,实时监测服务器连接数,优先选择连接数少的服务器处理新请求,让负载更均衡,适合处理请求时间差异大的场景。
  • 基于响应时间的调度(fair):借助第三方模块实现,依据后端服务器的响应时间分配请求。响应时间短的服务器,接收新请求的概率高,能让客户端更快得到响应,适用于对响应时间要求高的应用。

2.3http_proxy_module模块

特性 详情
功能 用于将客户端请求转发到后端HTTP服务器,实现反向代理和负载均衡
指令
proxy_pass 指定后端服务器地址,可以是IP地址加端口,也可以是一个定义好的upstream组名。例如proxy_pass http://backend_server; ,其中backend_server可以是具体地址如192.168.1.100:8080,也可以是在upstream块中定义的服务器组。
proxy_set_header 设置转发到后端服务器的请求头。如proxy_set_header Host $host; ,将客户端请求中的Host头原封不动转发给后端服务器,还可自定义头信息,像proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;用于记录客户端真实IP。
proxy_connect_timeout 设置与后端服务器建立连接的超时时间。默认60秒,例如proxy_connect_timeout 30s; ,表示尝试连接后端服务器超过30秒未成功则连接失败。
proxy_read_timeout 设置从后端服务器读取响应的超时时间。默认60秒,即如果在这个时间内没有从后端服务器读取到任何数据,连接将被关闭,如proxy_read_timeout 90s;
proxy_send_timeout 设置向后端服务器发送请求的超时时间。默认60秒,若在该时间内没有成功将请求数据发送到后端服务器,连接将被关闭,如proxy_send_timeout 45s;
proxy_buffer_size 设置用于读取后端服务器响应头的缓冲区大小。默认与proxy_buffers中的一个缓冲区大小相同,可根据实际情况调整,如proxy_buffer_size 128k;
proxy_buffers 设置用于读取后端服务器响应正文的缓冲区数量和大小。例如proxy_buffers 4 256k;表示设置4个大小为256KB的缓冲区。
proxy_busy_buffers_size 设置处于繁忙状态(正在被读取或写入)的缓冲区最大大小。默认值是proxy_buffers中两个缓冲区的大小,如proxy_busy_buffers_size 512k;
proxy_temp_path 设置临时文件存储路径,用于存储在处理大文件上传或响应时产生的临时数据。例如proxy_temp_path /var/tmp/nginx_proxy;
工作机制 客户端向Nginx发起请求,Nginx根据配置的proxy_pass指令将请求转发到后端服务器。在转发过程中,可通过proxy_set_header等指令修改请求头信息。Nginx等待后端服务器响应,根据设置的各种超时指令控制连接和数据传输的时间。响应数据返回后,Nginx根据缓冲区相关指令处理响应数据,再返回给客户端。
应用场景 广泛应用于Web服务器集群,实现反向代理和负载均衡,隐藏后端服务器真实IP,提升安全性;还可用于缓存加速,将频繁访问的内容缓存到Nginx,减少后端服务器压力。
  • 示例1:将匹配URI为name的请求抛给http://127.0.0.1/remote/.

    复制代码
    location /name/ {
    	proxy_pass http://127.0.0.1/remote/;
    }
  • 示例2:将匹配URI为some/path的请求抛给http://127.0.0.1

    复制代码
    location /some/path/ {
    	proxy_pass http://127.0.0.1;
    }
  • 示例3:将匹配URI为name的请求应用指定的rewrite规则,然后抛给http://127.0.0.1

    复制代码
    location /name/ {
    	rewrite /name/( [^/]+ ) /username=$1 break;
    	proxy_pass http://127.0.0.1;
    }

2.4 nginx负载均衡配置:

  • web服务器配置如上

  • 配置nginx负载均衡器

    复制代码
    [root@Rocky ~]# /etc/nginx/conf.d
    [root@Rocky conf.d]# vim vhost.conf
    upstream www_server_pools {
            server 172.25.254.103;	#默认监听端口80
            server 172.25.254.104;
    }
    server {
            listen 80;
            server_name www.yunjisuan.com;
            location / {
                    proxy_pass http://www_server_pools;
                    proxy_set_header Host $host;
                    proxy_set_header X-Forwarded-For $remote_addr;
            }
    }
    server {
            listen 80;
            server_name bbs.yunjisuan.com;
            location / {
                    proxy_pass http://www_server_pools;
                    proxy_set_header Host $host;
                    proxy_set_header X-Forwarded-For $remote_addr;
            }
    }
    [root@Rocky conf.d]# nginx -t
    [root@Rocky conf.d]# nginx -s reload
  • 在客户端测试

    复制代码
    ## 配置host解析
    [root@Rocky ~]# vim /etc/hosts
    172.25.254.101 bbs.yunjisuan.com www.yunjisuan.com
    [root@Rocky ~]# for ((i=1;i<=4;i++)); do curl http://bbs.yunjisuan.com; done
    172.25.254.103 . bbs
    172.25.254.104 . bbs
    172.25.254.103 . bbs
    172.25.254.104 . bbs
    [root@Rocky ~]# for ((i=1;i<=4;i++)); do curl http://www.yunjisuan.com; done
    172.25.254.103 . www
    172.25.254.104 . www
    172.25.254.103 . www
    172.25.254.104 . www
    ## 从上面的测试结果可以看出来。两个Web节点按照1:1的比例被访问。
    ## 下面宕掉任意一个Web节点,看看测试结果如何,测试如下
    ## 在172.25.254.103主机上停止nginx服务
    [root@Rocky conf.d]# systemctl stop nginx
    ## 继续测试
    [root@Rocky ~]# for ((i=1;i<=4;i++)); do curl http://www.yunjisuan.com; done
    172.25.254.104 . www
    172.25.254.104 . www
    172.25.254.104 . www
    172.25.254.104 . www
    [root@Rocky ~]# for ((i=1;i<=4;i++)); do curl http://bbs.yunjisuan.com; done
    172.25.254.104 . bbs
    172.25.254.104 . bbs
    172.25.254.104 . bbs
    172.25.254.104 . bbs
  • 由于添加proxy_set_header X-Forwarded-For $remote_addr,我们可以在web服务器的日志上查看真实访问ip

    复制代码
    [root@Rocky ~]# tail -3 /usr/share/nginx/html/www/logs/access_www.log
    172.25.254.101 - - [17/Mar/2025:17:34:08 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
    172.25.254.101 - - [17/Mar/2025:17:34:08 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
    172.25.254.101 - - [17/Mar/2025:17:34:08 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
    [root@Rocky ~]# tail -3 /usr/share/nginx/html/bbs/logs/access_bbs.log
    172.25.254.101 - - [17/Mar/2025:17:34:15 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
    172.25.254.101 - - [17/Mar/2025:17:34:15 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
    172.25.254.101 - - [17/Mar/2025:17:34:15 +0800] "GET / HTTP/1.0" 200 21 "-" "curl/7.61.1" "172.25.254.102"
相关推荐
乘云数字DATABUFF11 小时前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--2 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森2 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜3 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB4 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode5 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220706 天前
如何搭建本地yum源(上)
运维
ping某7 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树889 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠9 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql