负载均衡
将用户请求根据对应的算法, 分发到集群中的一台服务器上进行处理
作用
提升并发处理能力
提高单点故障宕机容错能力, 实现高可用
通过添加或减少服务器数量, 增强可扩展性
在负载均衡器上进行过滤, 提高系统安全性
常用实现方式
用户手动选择
比较原始的方式, 即提供不同线路, 由用户自己选择访问服务器
DNS轮询
由域名注册商解析同一域名到多主机IP, 随机访问不同IP, 也可以实现简单的负载均衡
但存在可靠性低(DNS缓存), 不均衡的问题
四/七层负载均衡
开放式系统互联模型 - OSI(open system interconnection)

四层负载均衡(传输层)
基于IP+Port实现, 包括硬件和软件实现方式:
- 硬件: F5 BIG-IP 、Radware等
- 软件: LVS、Nginx、Hayproxy等
七层负载均衡(应用层)
基于虚拟的URL或主机IP实现
四层负载均衡数据是在底层就进行分发, 而七层负载均衡则是在最顶端分发, 所以四层负载均衡效率更高
四层负载均衡不识别域名, 而七层负载均衡识别域名
一般实际环境使用四层负载(LVS) + 七层负载均衡(Nginx)
Nginx七层负载均衡
需要使用proxy_pass代理模块, 在反向代理的基础上将用户请求根据指定算法分发到[upstream虚拟服务池]
指令
upstram指令
用于定义一组服务器, 可以是不同端口, 也可以是监听TCP和Unix socket的服务器, 权重不指定, 默认为1
1 2 3 4
| 语法: upstream name{...} 位置: http块
|
server指令
用于指定后端服务器的名称及参数, 可以使用域名/IP/端口或Unix socket
1 2 3 4
| 语法: server name[parameters] 位置: upstream
|
实现流程

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| http { ... upstream serverpool{ server 192.168.253.135; server 192.168.253.136; server 192.168.253.137; } server{ listen 80; server_name test.project.com; location /{ proxy_pass http://serverpool; } } }
http { ... server{ listen 80; server_name localhost; location /{ default_type text/plain; return 200 '<h1>192.168.253.137</h1>'; } } }
|
实现结果

负载均衡状态
| 状态 |
概述 |
| down |
当前server不参与服务 |
| backup |
预留备份服务器 |
| max_fails |
允许请求失败次数, 默认1 |
| fail_timeout |
请求失败后, 服务暂停时间, 默认10s |
| max_conns |
限制最大的接收连接数, 默认0, 不限制 |
1 2 3 4 5
| upstream serverpool{ server 192.168.253.135 down; server 192.168.253.136 backup; server 192.168.253.137 max_fails=3 fail_timeout=15; }
|
使用配置之后, 由于浏览器缓存问题, 可能出现仍然访问到135服务器的状况, 可以用curl请求验证配置生效

负载均衡策略
Nginx的upstream支持六种分配算法, 分别是:
| 算法 |
概述 |
| 轮询 |
默认方式, 无需配置 |
| weight |
依权重点数分配 |
| ip_hash |
依据IP分配 |
| least_conn |
最少连接分配 |
| url_hash |
依据URL分配 |
| fair |
依响应时间分配 |
轮询策略
不做任何配置, 默认就是使用轮询策略
weight加权
也叫加权轮询, 使用weight=number设置server服务器的权重, 权重越大, 分配到的概率就越大, 主要是为了针对工作环境中不同配置的服务器配置
1 2 3 4 5
| upstream serverpool{ server 192.168.253.135 weight=10; server 192.168.253.136 weight=5; server 192.168.253.137 weight=5; }
|
ip_hash策略
通过请求客户端的IP,所计算出的哈希值定位到同一后端服务器上, 之后该客户端的请求均访问同一服务器, 可以解决用户session共享问题, 但无法保证后端服务器的负载均衡, 且设置后权重等配置将失效
1 2 3 4 5 6
| upstream serverpool{ ip_hash; server 192.168.253.135; server 192.168.253.136; server 192.168.253.137; }
|
least_conn策略
将请求转发给连接数较少的后端服务器上, 可以避免某些占用时间长的请求, 连续分发到同一服务器上, 达到更好的负载均衡效果
1 2 3 4 5 6
| upstream serverpool{ least_conn; server 192.168.253.135; server 192.168.253.136; server 192.168.253.137; }
|
url_hash策略
通过用户访问URL的哈希计算结果来分配请求访问目标, 使每一个URL定向到同一个后端服务器, 使其提高缓存命中率, 避免不必要的资源下载
1 2 3 4 5 6
| upstream serverpool{ hash $request_uri; server 192.168.253.135; server 192.168.253.136; server 192.168.253.137; }
|
fair策略
依据客户端请求页面大小、加载时间长短智能分发. 但不是nginx内建均衡算法, 需要引入第三方模块
1 2 3 4 5 6
| upstream serverpool{ fair; server 192.168.253.135; server 192.168.253.136; server 192.168.253.137; }
|
添加nginx-upstream-fair模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # https://github.com/gnosek/nginx-upstream-fair 下载fair压缩包 $ wget https://nginx.org/download/nginx-1.14.0.tar.gz $ unzip nginx-upstream-fair $ tar -zxvf nginx-1.14.0.tar.gz
$ cd nginx-1.14.0 $ vi src/http/ngx_http_upstream.h /ngx_http_upstream_srv_conf_s # 找到关键字 131 in_port_t default_port; # 131行添加内容 $ sudo apt install build-essential libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev libxslt1-dev libgd-dev libgroip-dev $ pwd ../nginx-upstream-fair $ nginx -V $ ./configure [nginx原有配置] --add-module=[fair-module路径] $ make $ sudo mv /usr/sbin/nginx /usr/sbin/nginx_old $ sudo cp objs/nginx /usr/sbin/nginx # $ sudo service nginx restart $ make upgrade
|
实际案例
特定资源负载均衡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| http { ... upstream video_pool{ server 192.168.253.135; server 192.168.253.136; } upstream file_pool{ server 192.168.253.137; server 192.168.253.138; } server{ listen 80; server_name localhost; location /video{ proxy_pass http://video_pool; } location /file{ proxy_pass http://file_pool; } } }
|


对不同域名实现负载均衡
修改客户端本地hosts文件(C:\Windows\System32\drivers\etc\hosts), 添加内容
1 2
| 192.168.253.134 local1.project.com 192.168.253.134 local2.project.com
|
修改服务器nginx配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| upstream local1{ server 192.168.253.135; server 192.168.253.136; } upstream local2{ server 192.168.253.137; server 192.168.253.138; }
server{ listen 80; server_name local1.project.com; location /{ proxy_pass http://local1; } } server{ listen 80; server_name local2.project.com; location /{ proxy_pass http://local2; } }
|


带URL重写的负载均衡
重写请求中以file开头的路由, 到new路由中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| upstream rewrite_pool{ server 192.168.253.135 weight=2; server 192.168.253.136 weight=1; server 192.168.253.137 weight=1; } server{ listen 80; server_name localhost; location /file/{ rewrite ^(/file/.*/) /new/$1 last; } location /new{ proxy_pass http://rewrite_pool; } }
|
Nginx 四层负载均衡
Nginx 的四层协议转发、代理、负载均衡, 是通过stream模块实现的. 允许配置一组TCP/UDP等协议的监听, 然后通过proxy_pass转发请求, 通过upstream添加多个后端服务, 实现负载均衡
添加stream模块支持
1 2 3 4 5 6
| $ sudo mv /usr/sbin/nginx /usr/sbin/nginx_old $ nginx -V $ ./configure [nginx原有配置] --with-stream $ make $ sudo cp objs/nginx /usr/sbin/nginx $ sudo service nginx restart
|

stream模块指令
stream指令
提供在其中指定流服务器的配置文件上下文, 和http块同级
1 2 3 4
| 语法: stream{...} 位置: main
|
upstream指令
与upstream模块中类似, 但位置处于stream块内部
实际案例
访问负载均衡分发服务器的8088端口时, 将请求分发到两台服务器的redis服务中
1 2 3 4 5 6 7 8 9 10 11 12
| stream{ upstream redis_backend{ server 192.168.253.135:6379; server 192.168.253.136:6379; } server{ listen 8088; proxy_pass redis_backend; } }
|
结果:
