1、Nginx四层负载均衡
1.1 负载均衡概述
-
负载均衡是一种分布式计算技术,用于将网络流量和用户请求分散到多台服务器上,以此来提高网络服务的可用性和可靠性。它通过优化资源使用、最大化吞吐量以及最小化响应时间,增强了网络、服务器和数据中心的伸缩性和灵活性。
-
Nginx的负载均衡功能主要通过其反向代理模式实现。当客户端发送请求到Nginx服务器时,Nginx会根据预设的负载均衡策略将请求转发给后端服务器,并将后端服务器的响应返回给客户端。Nginx作为代理服务器,有效地分摊了请求压力,提高了系统的处理能力。
1.2 负载均衡的目的
-
提高可用性:通过将请求分散到多个服务器,即使部分服务器出现故障,整个系统仍然可以继续提供服务。
-
增强性能:负载均衡可以提高系统处理大量并发请求的能力,从而提升整体性能。
-
故障转移:当一台服务器发生故障时,负载均衡器可以自动将流量转移到其他健康的服务器上,以避免服务中断。
-
降低延迟:通过选择最佳的服务器来处理请求,减少数据传输的延迟。
-
资源优化:合理分配请求到各个服务器,避免某些服务器过载而其他服务器空闲,优化资源使用。
1.3 Nginx的负载均衡调度算法
1.3.1 轮询(Round Robin)
-
轮询是最简单的负载均衡算法,它将请求按顺序分发到每个服务器。当一个请求被发送到一个服务器后,下一个请求将被发送到列表中的下一个服务器。这种方法简单易行使用,但可能不适合所有场景,特别是当某些服务器的处理能力不同时。
1.3.2 最少连接(Least Connections)
-
最少的连接算法将请求发送到当前连接数最少的服务器。这种方法可以更有效地利用服务器资源,因为它完全避免过载服务器。然而,这种方法可能会导致负载不均衡,特别是在服务器性能差异方面更大的情况发生。
1.3.3 IP哈希(IP Hash)
-
IP哈希算法根据客户端的IP地址哈希值将请求发送到服务器。该方法可以保证来自相同客户端的这种请求总是被发送到相同服务器,这对于需要会话保持的应用程序很有用。该方法可能会导致负载不均衡,特别是在服务器数量变化时。
1.3.4 加权轮询(Weighted Round Robin)
-
加权轮询是轮询算法的一个变体,它允许为每个服务器分配重权。权重损失的服务器将接收到更多的请求。这种方法可以根据服务器的性能和负载情况动态调整负载分配。
1.3.5 加权最少连接(Weighted Least Connections)
-
加权最小连接算法结合了最小连接和加权轮询的概念。它根据服务器的权重和当前连接数来选择服务器,以实现更平衡的负载分配。
1.3.6 哈希(Hash)
-
哈希算法根据请求的某些属性(如 URL 或请求头)来选择服务器。这种方法可以保证相同的请求总是被发送到相同的服务器,但需要注意的是,如果服务器数量发生变化,可能会导致负载不均衡。
1.4 Nginx四层负载均衡基本配置
主机 | IPV4地址 | 版本 |
---|---|---|
proxy (代理) |
192.168.110.31/24 | Rocky-Linux 8 |
web-01 (主机-01) |
192.168.110.32/24 | Rocky-Linux 8 |
web-02 (主机-02) |
192.168.110.33/24 | Rocky-Linux 8 |
web-03 (主机-03) |
192.168.110.34/24 | Rocky-Linux 8 |
client (客户端) |
192.168.110.35/24 | Rocky-Linux 8 |
1.4.1 后端主机配置
1.4.1.1 web-01配置
[root@web-01 ~]# mkdir -p /nginx/web [root@web-01 ~]# echo "This is `hostname` IP=`hostname -I`" >> /nginx/web/index.html [root@web-01 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.32:80; root /nginx/web; location /{ index index.html; } } [root@web-01 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-01 ~]# nginx -s reload [root@web-01 ~]# curl 192.168.110.32 This is web-01 IP=192.168.110.32
1.4.1.2 web-02配置
[root@web-02 ~]# mkdir -p /nginx/web [root@web-02 ~]# echo "This is `hostname` IP=`hostname -I`" >> /nginx/web/index.html [root@web-02 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.33:80; root /nginx/web; location /{ index index.html; } } [root@web-02 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-02 ~]# nginx -s reload [root@web-02 web]# curl 192.168.110.33 This is web-02 IP=192.168.110.33
1.4.1.3 web-03配置
[root@web-03 ~]# mkdir -p /nginx/web [root@web-03 ~]# echo "This is `hostname` IP=`hostname -I`" >> /nginx/web/index.html [root@web-03 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.34:80; root /nginx/web; location /{ index index.html; } } [root@web-03 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-03 ~]# nginx -s reload [root@web-03 ~]# curl 192.168.110.34:80 This is web-03 IP=192.168.110.34
1.4.2 代理服务器配置
[root@proxy ~]# vim /etc/nginx/conf.d/proxy.conf upstream wwwPools { server 192.168.110.32; server 192.168.110.33; server 192.168.110.34; } server { location / { proxy_pass http://wwwPools; } } [root@proxy ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@proxy ~]# nginx -s reload
1.4.3 客户端端访问测试
[root@client ~]# for ((i=1;i
1.4.4 upstream模块参数解释
参数 | 说明 |
---|---|
server | 定义后端服务器的IP地址或域名,可选地指定端口号,默认为80端口。 |
weight | 服务器权重,默认为1。权重越高,处理的请求比例越大。 |
max fails | Nginx尝试连接后端服务器失败的次数,默认为1。超过此次数,Nginx将服务器标记为失败。 |
fail timeout | 在max fails 定义的失败次数后,距离下次检查的间隔时间,默认为10秒。 |
backup | 热备配置,仅当所有激活的服务器失败后,请求才会被转发到标记为backup 的服务器。 |
down | 标记服务器永远不可用,通常用于维护或测试。配合ip_hash 使用时,服务器不能被标记为down 。 |
1.4.5 增加权重
[root@proxy ~]# vim /etc/nginx/conf.d/proxy.conf upstream wwwPools { server 192.168.110.32 weight=1; server 192.168.110.33 weight=2; server 192.168.110.34 weight=3 down; } server { location / { proxy_pass http://wwwPools; } } [root@proxy ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@proxy ~]# nginx -s reload 访问测试 [root@client ~]# for ((i=1;i
1.5 多台虚拟主机之间基于端口实现负载均衡
1.5.1 后端主机配置
1.5.1.1 web-01配置
[root@web-01 ~]# echo "This is `hostname` IP:`hostname -I` port=80" >> /nginx/web/index80.html [root@web-01 ~]# echo "This is `hostname` IP:`hostname -I` port=81" >> /nginx/web/index81.html [root@web-01 ~]# echo "This is `hostname` IP:`hostname -I` port=82" >> /nginx/web/index82.html [root@web-01 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.32:80; root /nginx/web; location /{ index index80.html; } } server { listen 192.168.110.32:81; root /nginx/web; location /{ index index81.html; } } server { listen 192.168.110.32:82; root /nginx/web; location /{ index index82.html; } } [root@web-01 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-01 ~]# nginx -s reload [root@web-01 ~]# curl 192.168.110.32:80 This is web-01 IP:192.168.110.32 port=80 [root@web-01 ~]# curl 192.168.110.32:81 This is web-01 IP:192.168.110.32 port=81 [root@web-01 ~]# curl 192.168.110.32:82 This is web-01 IP:192.168.110.32 port=82
1.5.1.2 web-02配置
[root@web-02 web]# echo "This is `hostname` IP:`hostname -I` port=80" >> /nginx/web/index80.html [root@web-02 web]# echo "This is `hostname` IP:`hostname -I` port=81" >> /nginx/web/index81.html [root@web-02 web]# echo "This is `hostname` IP:`hostname -I` port=82" >> /nginx/web/index82.html [root@web-02 web]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.33:80; root /nginx/web; location / { index index80.html; } } server { listen 192.168.110.33:81; root /nginx/web; location / { index index81.html; } } server { listen 192.168.110.33:82; root /nginx/web; location / { index index82.html; } } [root@web-02 web]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-02 web]# nginx -s reload [root@web-02 ~]# curl 192.168.110.33:80 This is web-02 IP:192.168.110.33 port=80 [root@web-02 ~]# curl 192.168.110.33:81 This is web-02 IP:192.168.110.33 port=81 [root@web-02 ~]# curl 192.168.110.33:82 This is web-02 IP:192.168.110.33 port=82
1.5.1.3 web-03配置
[root@web-03 ~]# echo "This is `hostname` IP:`hostname -I` port=80" >> /nginx/web/index80.html [root@web-03 ~]# echo "This is `hostname` IP:`hostname -I` port=81" >> /nginx/web/index81.html [root@web-03 ~]# echo "This is `hostname` IP:`hostname -I` port=82" >> /nginx/web/index82.html [root@web-03 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.34:80; root /nginx/web; location / { index index80.html; } } server { listen 192.168.110.34:81; root /nginx/web; location / { index index81.html; } } server { listen 192.168.110.34:82; root /nginx/web; location / { index index82.html; } } [root@web-03 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-03 ~]# nginx -s reload [root@web-03 ~]# curl 192.168.110.34:80 This is web-03 IP:192.168.110.34 port=80 [root@web-03 ~]# curl 192.168.110.34:81 This is web-03 IP:192.168.110.34 port=81 [root@web-03 ~]# curl 192.168.110.34:82 This is web-03 IP:192.168.110.34 port=82
1.5.2 代理服务器配置
[root@proxy ~]# vim /etc/nginx/conf.d/proxy.conf upstream wwwPools { server 192.168.110.32:80; server 192.168.110.33:80; server 192.168.110.34:80; server 192.168.110.32:81; server 192.168.110.33:81; server 192.168.110.34:81; server 192.168.110.32:82; server 192.168.110.33:82; server 192.168.110.34:82; } server { location / { proxy_pass http://wwwPools; } } [root@proxy ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@proxy ~]# nginx -s reload
1.5.3 客户端访问测试
[root@client ~]# for ((i=1;i<=12;i++)); do curl http://www.proxy.com; done This is web-01 IP:192.168.110.32 port=80 This is web-02 IP:192.168.110.33 port=80 This is web-03 IP:192.168.110.34 port=80 This is web-01 IP:192.168.110.32 port=81 This is web-02 IP:192.168.110.33 port=81 This is web-03 IP:192.168.110.34 port=81 This is web-01 IP:192.168.110.32 port=82 This is web-02 IP:192.168.110.33 port=82 This is web-03 IP:192.168.110.34 port=82 This is web-01 IP:192.168.110.32 port=80 This is web-02 IP:192.168.110.33 port=80 This is web-03 IP:192.168.110.34 port=80
1.6 反向代理多虚拟主机节点服务器
1.6.1 模块主要参数
在 Nginx 的配置中使用 proxy_set_header
指令是为了在 Nginx 作为反向代理服务器时,向真实的后端服务器传递客户端的原始信息。以下是对 proxy_set_header
指令的详细解释,以及它如何影响代理请求:
proxy_set_header host $host;
这条指令的作用是:
-
proxy_set_header
:这是 Nginx 用来设置由代理服务器发送给后端服务器的 HTTP 请求头的指令。 -
host
:这是 HTTP 请求头中的一个字段,通常包含了客户端请求的原始主机信息,如域名或 IP 地址。 -
$host
:这是 Nginx 变量,它代表客户端请求中的Host
头部的值。
1.6.2 为什么需要 proxy_set_header host $host;
-
当 Nginx 作为反向代理时,它默认会将客户端的请求转发给配置好的后端服务器,但是在这个过程中,原始的
Host
请求头可能会丢失或被修改。这可能导致后端服务器无法正确识别客户端请求的虚拟主机,尤其是在后端服务器配置了多个虚拟主机时。 -
例如,如果客户端发送了一个带有
Host: www.yunjisuan.com
的请求,但是 Nginx 在转发请求时没有保留这个Host
头部,后端服务器可能会默认提供一个它配置的第一个虚拟主机的响应,而不是客户端请求的那个特定的虚拟主机。
1.6.3 配置示例
1.6.3.1 web-01配置
[root@web-01 ~]# mkdir -p /nginx/web-{1..3} [root@web-01 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-1" >> /nginx/web-1/index.html [root@web-01 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-2" >> /nginx/web-2/index.html [root@web-01 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-3" >> /nginx/web-3/index.html [root@web-01 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.32:80; server_name www.web-01.com; root /nginx/web-1; location /{ index index.html; } } server { listen 192.168.110.32:80; server_name www.web-02.com; root /nginx/web-2; location /{ index index.html; } } server { listen 192.168.110.32:80; server_name www.web-03.com; root /nginx/web-3; location /{ index index.html; } } [root@web-01 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-01 ~]# nginx -s reload
1.6.3.2 web-02配置
[root@web-02 ~]# mkdir -p /nginx/web-{1..3} [root@web-02 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-1" >> /nginx/web-1/index.html [root@web-02 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-2" >> /nginx/web-2/index.html [root@web-02 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-3" >> /nginx/web-3/index.html [root@web-02 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.33:80; server_name www.web-01.com; root /nginx/web-1; location /{ index index.html; } } server { listen 192.168.110.33:80; server_name www.web-02.com; root /nginx/web-2; location /{ index index.html; } } server { listen 192.168.110.33:80; server_name www.web-03.com; root /nginx/web-3; location /{ index index.html; } } [root@web-02 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-02 ~]# nginx -s reload
1.6.3.3 web-03配置
[root@web-03 ~]# mkdir -p /nginx/web-{1..3} [root@web-03 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-1" >> /nginx/web-1/index.html [root@web-03 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-2" >> /nginx/web-2/index.html [root@web-03 ~]# echo "This is `hostname` IP=`hostname -I` dir=/nginx/web-3" >> /nginx/web-3/index.html [root@web-03 ~]# vim /etc/nginx/conf.d/VirtualHost.conf server { listen 192.168.110.34:80; server_name www.web-01.com; root /nginx/web-1; location /{ index index.html; } } server { listen 192.168.110.34:80; server_name www.web-02.com; root /nginx/web-2; location /{ index index.html; } } server { listen 192.168.110.34:80; server_name www.web-03.com; root /nginx/web-3; location /{ index index.html; } } [root@web-03 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@web-03 ~]# nginx -s reload
1.6.3.4 代理服务器配置(不加proxy_set_header host $host;)
[root@proxy ~]# vim /etc/nginx/conf.d/proxy.conf upstream wwwPools { server 192.168.110.32:80; server 192.168.110.33:80; server 192.168.110.34:80; } server { listen 80; server_name www.web-01.com; location / { proxy_pass http://wwwPools; } } server { listen 80; server_name www.web-02.com; location / { proxy_pass http://wwwPools; } } server { listen 80; server_name www.web-03.com; location / { proxy_pass http://wwwPools; } } [root@proxy ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@proxy ~]# nginx -s reload
1.6.3.5 客户端访问
[root@client ~]# echo '192.168.110.31 www.web-01.com www.web-02.com www.web-03.com' >> /etc/hosts #添加hosts解析,ip为proxy的ip [root@client ~]# for ((i=1;i
注意:若后端有多台虚拟主机如果不添加proxy_set_header host $host;的话代理服务器无法判断代理的是哪个虚拟主机,所以不管访问的是哪个域名返还的都是第一台虚拟主机的内容
1.6.3.6 代理服务器配置包含proxy_set_header host $host;
[root@proxy ~]# vim /etc/nginx/conf.d/proxy.conf upstream wwwPools { server 192.168.110.32:80; server 192.168.110.33:80; server 192.168.110.34:80; } server { listen 80; server_name www.web-01.com; location / { proxy_pass http://wwwPools; proxy_set_header host $host; proxy_set_header X-Forwarded-For $remote_addr; } } server { listen 80; server_name www.web-02.com; location / { proxy_pass http://wwwPools; proxy_set_header host $host; proxy_set_header X-Forwarded-For $remote_addr; } } server { listen 80; server_name www.web-03.com; location / { proxy_pass http://wwwPools; proxy_set_header host $host; proxy_set_header X-Forwarded-For $remote_addr; } } [root@proxy ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@proxy ~]# nginx -s reload
指令 | 参数 | 说明 |
---|---|---|
proxy_set_header | host $host | 设置代理请求中的Host 头部,值为原始请求中的Host 头部。这确保了后端服务器能够识别客户端请求的虚拟主机。 |
proxy_set_header | X-Forwarded-For $remote_addr | 设置代理请求中的X-Forwarded-For 头部,值为客户端的IP地址。这个头部用于记录客户端真实的IP地址,支持识别通过HTTP代理或负载均衡器发送的请求。 |
1.6.3.6 客户端访问
[root@client ~]# for ((i=1;i
1.6.3.7 查看访问日志
[root@web-01 ~]# tail -3 /var/log/nginx/access.log 192.168.110.31 - - [21/Apr/2024:15:31:38 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:39 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:41 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" [root@web-02 ~]# tail -3 /var/log/nginx/access.log 192.168.110.31 - - [21/Apr/2024:15:31:38 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:39 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:41 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" [root@web-03 ~]# tail -3 /var/log/nginx/access.log 192.168.110.31 - - [21/Apr/2024:15:31:38 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:39 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35" 192.168.110.31 - - [21/Apr/2024:15:31:41 +0800] "GET / HTTP/1.0" 200 52 "-" "curl/7.61.1" "192.168.110.35"
到此这篇关于Nginx四层负载均衡的实现示例的文章就介绍到这了,更多相关Nginx四层负载均衡内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!