# Nginx 代理 - 负载均衡实践

# 1.Nginx 负载均衡基本概述

# 1.1 什么是负载均衡

负载均衡 Load Balance,指的是将用户访问请求所产生的流量,进行平衡,分摊到多个应用节点处理。负载均衡扩展了应用的服务能力,增强了应用的可用性。

# 1.2 为什么需要负载均

当我们的 Web 服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台 WEB 服务器组成集群,前端使用 Nginx 负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的流量分发。从而提升整体性能、以及系统的容灾能力。

1.png

# 1.3 负载均衡与代理区别

Nginx 负载均衡与 Nginx 反向代理不同地方在于:

  • Nginx 代理仅代理一台服务器基于 URI 来调度,调度到不同功能的应用节点处理。
  • Nginx 负载均衡则是将客户端请求通过 proxy_pass 代理至一组 upstream 资源池。

# 2.Nginx 负载均衡应用场景

# 2.1 四层负载均衡

四层负载均衡指的是 OSI 七层模型中的传输层,四层仅需要对客户端的请求进行 TCP/IP 协议的包代理就可以实

现负载均衡。IP+Port

四层负载均衡的性能极好、因为只需要底层进行转发处理,而不需要进行一些复杂的逻辑。

2.png

# 2.2 七层负载均衡

七层负载均衡工作在应用层,它可以完成很多应用方面的协议请求,比如我们说的 http 应用负载均衡,它可以实现 http 头信息的改写、安全应用规则控制、URI 匹配规则控制、及 rewrite 等功能,所以在应用层里面可以做的内容就更多了。

3.png

# 2.3 四层与七层区别

四层负载均衡:传输层

  • 优点:性能高,数据包在底层就进行了转发
  • 缺点:仅支持 ip:prot 转发,无法完成复杂的业务逻辑应用。
  • MySQL TCP 3306, Redis、SSH、等;

七层负载均衡:应用层

  • 优点:贴近业务,支持 URI 路径匹配、Header 改写、Rewrite 等
  • 缺点:性能低,数据包需要拆解到顶层才进行调度,消耗随机端口;

# 3.Nginx 负载均衡配置场景

# 3.1 负载均衡场景环境规划

负载均衡场景架构图规划:

4.png

负载均衡场景地址规划:

角色外网 IP (NAT)内网 IP (LAN)主机名
lb01eth0:10.0.0.5eth1:172.16.1.5lb01
web01eth0:10.0.0.7eth1:172.16.1.7web01
web02eth0:10.0.0.8eth1:172.16.1.8web02
# 3.2 后端 Web 节点配置实例

1.Web01 服务器上配置为应用服务节点,创建对应 html 文件

[root@web01 ~]# cat /etc/nginx/conf.d/web.hmallleasing.com.conf
server {
	listen 80;
	server_name web.hmallleasing.com;
	root /code/web;
	
	location / {
		index index.html;
	}
}
[root@web01 conf.d]# mkdir /code/web
[root@web01 conf.d]# echo "Web01..." > /code/web/index.html
[root@web01 conf.d]# systemctl restart nginx

2.Web02 服务器上配置为应用服务节点,创建对应 html 文件

[root@web02 ~]# cat /etc/nginx/conf.d/web.hmallleasing.com.conf
server {
	listen 80;
	server_name web.hmallleasing.com;
	root /code/web;
	
	location / {
		index index.html;
	}
}
[root@web02 conf.d]# mkdir /code/web
[root@web02 conf.d]# echo "Web02..." > /code/web/index.html
[root@web02 conf.d]# systemctl restart nginx
# 3.3. 前端接入 Nginx 负载均衡

1. 将 lb01 配置为负载均衡,将所有请求代理至虚拟资源池

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf
upstream web {
	server 172.16.1.7:80;
	server 172.16.1.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
[root@lb01 conf.d]# systemctl restart nginx

2. 准备 Nginx 负载均衡需要使用的 proxy_params 文件

[root@lb01 conf.d]# vim /etc/nginx/proxy_params
proxy_http_version 1.1;
proxy_set_header Connectin "";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 120;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_temp_file_write_size 10240k;
proxy_max_temp_file_size 10240k;
# 3.4. 浏览器访问测试负载效果

使用浏览器访问 web.oldxu.com,然后进行刷新测试。

1.jpg

# 4.Nginx 负载均衡调度算法

调度算法概述
轮询按时间顺序逐一分配到不同的后端服务器 (默认)
weight加权轮询,weight 值越大,分配到的访问几率越高
ip_hash每个请求按访问 IP 的 hash 结果分配,这样来自同一 IP 的固定访问一个后端服务器
url_hash根据请求 uri 进行调度到指定节点
least_conn将请求传递到活动连接数最少的服务器。
# 4.1 轮询调度算法

轮询调度算法的原理是将每一次用户的请求,轮流分配给内部中的服务器。

轮询算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 4.2 加权轮询调度算法

轮询调度算法没有考虑每台服务器的处理能力,在实际情况中,由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	server 192.168.40.7:80 weight=5;
	server 192.168.40.8:80 weight=1;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 4.3 ip_hash 调度算法

ip_hash 是基于用户请求的 IP,对该 IP 进行 hash 运算,根据 hash 运算的值,将请求分配到后端特定的一台节点进行处理。ip_hash 算法实现公式:hash (ip) % node_counts = index

2.jpg

如何配置 ip_hash 调度算法:

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	ip_hash;
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}

ip_hash 调度算法会带来两个问题:

  • 1. 如果有大量来自于同一 IP 的请求会造成某个后端节点流量过大,而其他节点无流量
  • 2. 如果临时下线一台节点,会出现重新计算 hash 值,官方建议将下线节点标记为 down 状态,以保留客户端 IP 地址的当前哈希值。(如下图所示:)

3.jpg

如果有大量的用户调度到某一节点,而该节点刚好故障,则该算法会重新计算结果,从而造成大量的用户被转移其他节点处理,而需要重新建立会话。

# 4.4 一致性 hash 调度算

为了规避上述 hash 情况,一致性 hash 算法就诞生,一致性 Hash 算法也是使用取模的方法,但不是对服务器节点数量进行取模,而是对 2 的 32 方取模。即,一致性 Hash 算法将整个 Hash 空间组织成一个虚拟的圆环,Hash 函数值的空间为 0 ~ 2^32 - 1,整个哈希环如下:

https://www.jianshu.com/p/528ce5cd7e8f

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	hash $remote_addr consistent;
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 4.5 url_hash 调度算法

根据用户请求的 URL 进行 hash 取模,根据 hash 运算的值,将请求分配到后端特定的一台节点进行处理。URL 算法使用场景如下:client-->nginx-->url_hash-->cache1-->app

  • 1. 用户请求 nginx 负载均衡器,通过 url 调度算法,将请求调度至 Cache1
  • 2. 由于 Cache1 节点没有对应的缓存数据,则会请求后端获取,然后返回数据,并将数据缓存起来;
  • 3. 当其他用户再次请求此前相同的 URL 时,此时调度器依然会调度至 Cache1 节点处理;
  • 4. 由于 Cache1 节点已存在该 URL 资源缓存,所以直接将缓存数据进行返回;能大幅提升网站的响应;

1. 配置后端节点

# web1 节点
[root@web01 ~]# echo "web1 Url1" > /code/web/url1.html
[root@web01 ~]# echo "web1 Url2" > /code/web/url2.html
# web2 节点
[root@web02 ~]# echo "web2 Url1" > /code/web/url1.html
[root@web02 ~]# echo "web2 Url2" > /code/web/url2.html

2. 负载均衡配置 url_hash 调度算法

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	# 请求同一个 url,会始终定向到同一个服务器节点,consistent 表示使用一致性 hash 算法
	hash $request_uri consistent;
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}

3.Client 测试,会发现请求相同的 URL,始终会被定向至某特定后端节点。

[root@lb01 ~]#  curl -HHost:web.hmallleasing.com http://192.168.40.150/url1.html
web2 Url1
[root@lb01 ~]#  curl -HHost:web.hmallleasing.com http://192.168.40.150/url2.html
web1 Url2
# 4.6 least_conn 调度算法

least_conn 调度算法实现原理,哪台节点连接数少,则将请求调度至哪台节点。

假设:A 节点有 1000 个连接 、b 节点有 500 连接,如果此时新的连接进入会分发给 b 节点

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	least_conn;
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}

# 5.Nginx 负载均衡后端状态

后端 Web 节点在前端 Nginx 负载均衡调度中的状态

状态概述
down当前的 server 暂时不参与负载均衡
backup预留的备份服务器
max_fails允许请求失败的次数
fail_timeout经过 max_fails 失败后,服务暂停时间
max_conns限制最大的接收连接数
# 5.1 max_conns 限制连接数

max_conns 用来限制每个后端节点能够接收的最大 TCP 连接数,如果超过此连接则会抛出错误。

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
    #接收的最大 TCP 连接数
	server 192.168.40.7:80 max_conns=2;
	server 192.168.40.8:80 max_conns=2;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}

1、配置 jmeter

a、添加线程组:添加 -> 线程用户 -> 线程组

1.jpg

b、添加 HTTP 请求:添加 -> 取样器 ->HTTP 请求

2.jpg

c. 添加聚合报告:添加 -> 监听器 -> 聚合报告

d. 添加察看结果树:添加 -> 监听器 -> 察看结果树

e. 添加用表格察看结果:添加 -> 监听器 -> 用表格察看结果

2、通过 jmter 压力测试发现,当后端节点处理的连接数非常多的时候,当大于 4 个连接,其余的连接则会抛出异常,也就是每次仅能满足 4 个连接。

3.jpg

# 5.2 down 标识关闭状态

down 将服务器标记为不可用状态。

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	#临时停机维护
	server 192.168.40.7:80 down;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 5.3 backup 标识备份状态

backup 将服务器标记为备份服务器。当主服务器不可用时,将请求传递至备份服务器处理。

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	server 192.168.40.7:80 backup;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 5.4 max_fails 与 fail_timeout

max_fails=2 服务器通信失败尝试 2 次,任然失败,认为服务器不可用,默认值 1;

fail_timeout=5s 服务器通信失败后,每 5s 探测一次节点是否恢复可用,默认值 10s;

在 fail_timeout 设定的时间内,与服务器连接失败达到 max_fails 则认为服务器不可用;

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
    #失败尝试 2 次,如果失败了每 5s 探测一次
	server 192.168.40.7:80 max_fails=2 fail_timeout=5s;
	server 192.168.40.8:80 max_fails=2 fail_timeout=5s;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
# 5.5 keepalived 提升吞吐量

keepalive 主要是与后端服务器激活缓存,也就是长连接,主要用来提升网站吞吐量。

默认情况下:没有与后端服务启用长连接功能,当有请求时,需要建立连接、维护连接、关闭连接,所以会存在网络消耗,但如果将所有的连接都缓存了,当连接空闲了又会占用其系统资源,所以可以使用 keepalive 参数来激活缓存,同时还可以使用 keepalive 参数来限制最大的空闲连接数;

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	#keepalive 32;                       #最大的空闲连接数
	#keepalive_timeout 100s;             #空闲连接的超时时间
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
[root@lb01 ~]# cat /etc/nginx/proxy_params
#proxy_http_version 1.1;
#proxy_set_header Connectin "";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 120;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_temp_file_write_size 10240k;
proxy_max_temp_file_size 10240k;

没有启用 keepalive 参数前,对集群进行压力测试

4.jpg

配置 Nginx 负载均衡启用 keepalive 参数:

[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	keepalive 32;                       #最大的空闲连接数
	keepalive_timeout 100s;             #空闲连接的超时时间
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
	}
}
[root@lb01 ~]# cat /etc/nginx/proxy_params
#启用长连接
proxy_http_version 1.1;
proxy_set_header Connectin "";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 120;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_temp_file_write_size 10240k;
proxy_max_temp_file_size 10240k;

对启用 keepalive 参数后的集群进行压力测试,发现整体性能提升了一倍。

5.jpg

# 6. 后端节点异常容错机制

使用 nginx 负载均衡时,如何将后端请求超时的服务器流量平滑的切换到另一台上。

如果后台服务连接超时,Nginx 是本身是有机制的,如果出现一个节点 down 掉的时候,Nginx 会更据你具体负载均衡的设置,将请求转移到其他的节点上,但是,如果后台服务连接没有 down 掉,而是返回了错误异常码如:504、502、500,该怎么办

# 6.1 配置语法
# 当其中一台返回错误码 404,500 等错误时,可以分配到下一台服务器程序继续处理,提高平台访问成功率。
proxy_next_upstream http_500 | http_502 | http_503 | http_504 |http_404;
# 6.2 场景示例
[root@lb01 ~]# cat /etc/nginx/conf.d/proxy_web.hmallleasing.com.conf 
upstream web {
	keepalive 32;                       #最大的空闲连接数
	keepalive_timeout 100s;             #空闲连接的超时时间
	server 192.168.40.7:80;
	server 192.168.40.8:80;
}
server {
	listen 80;
	server_name web.hmallleasing.com;
	
	location / {
		proxy_pass http://web;
		include proxy_params;
		#当其中一台返回错误 500,502,503,504 时,分配下一台服务器程序处理,提高平台访问成功率
		proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
		proxy_next_upstream_tries 2;
		proxy_next_upstream_timeout 3s;
	}
}
[root@lb01 ~]# cat /etc/nginx/proxy_params
#启用长连接
proxy_http_version 1.1;
proxy_set_header Connectin "";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 120;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_temp_file_write_size 10240k;
proxy_max_temp_file_size 10240k;
此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Xu Yong 微信支付

微信支付

Xu Yong 支付宝

支付宝