原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://lyp0909.blog.51cto.com/508999/546865
首先说下提高服务器响应能力的常见方法如下:
纵向扩展(scale on):在原有服务器的基础上进行硬件升级。
横向扩展(scale out):部署多台服务器并发向外响应客户端的请求。优点:成本低,扩展架构比较简单。
集群(Cluster):通俗地讲就是按照某种原则将几台电脑组织起来,完成某种特定任务的这样一种架构。
三种集群类型:
LB,Load Balancing 负载均衡集群:在一定程度上能够实现高可用的目的。
HA,High Availability 高可用集群:实时在线,无中断提供服务,企业应用要求达到
7*24小时,99.999%时间在线。
HP,High Performance 高性能集群 提供大量超级运算能力的集群。
LB 负载均衡架构:
Director(dispatcher):负责接收客户端请求,并将请求按照某种算法分发到后台真正提供服务的服务器上。既可以基于硬件(如F5)来实现,也可以基于软件来实现。
基于软件实现的又分为四层交换:基于IP地址和端口号组合起来对服务做重定向(LVS)。七层交换:通常指的是反向代理(proxy),例如:squid。
LVS:Linux Virtual Server
类似于iptables的架构,ipvs:在内核中有一段实时监听数据包来源请求的代码,当数据包到达监听端口时做一次重定向,在内核中实现数据包请求处理的代码叫做ipvs。ipvs仅仅提供了功能框架,还需要自己手动定义是数据对哪个服务的请求,而这种定义需要通过写规则来实现,写规则的工具就称为ipvsadm。在内核空间中工作的是"ipvs",而在用户空间中工作的,用来定义集群服务规则的是"ipvsadm"
使用环境:
高吞吐量(higher throughput)
冗余 (redundancy)
自适应性 (adaptability)
LVS负载均衡架构
Virtual IP(VIP)address:Director用来向客户端提供服务的IP地址
Real IP (RIP) address:集群节点(后台真正提供服务的服务器)所使用的IP地址
Director's IP (DIP) address:Director用来和D/RIP 进行联系的地址
Client computer's IP (CIP) address:公网IP,客户端使用的IP。
根据前端Director和后台Real Server的通信方式将LVS分为三类:
Network Address Translation(LVS-NAT):
目标地址转换 所有客户端的请求都被Director根据访问请求和算法被定向到后台的Real Server 上。
数据包地址转换过程:
S:CIP D:VIP------->Director------>S:CIP D:RIP------>Real Server----->S:RIP D:CIP----->Director----->S:VIP D:CIP
1、Director的DIP和Real Server的RIP必须在同一个网段中;
2、一般情况下,RIP是私有地址,只用于集群内部节点间通信;
3、Director 会响应所有客户端和Real Server之间的请求和应答数据,所承担的负载较大;
4、所有的Real IP 网关必须指向DIP以响应客户端请求;
5、Director可以映射网络端口,即前端使用标准端口,后端可以使用非标准端口;
6、后台的Real Server可以使用任何操作系统;
缺点:Director可能会成为系统瓶颈,可以支持real server数量10-20台。
Director routing (LVS-DR ):
直接路由:客户端请求经过Director,Real Server直接回应客户端
数据包地址转换过程:
S:CIP D:VIP----->Director--->S:CIP D:RIP -----> Real Server---> S:VIP D:CIP
注意:Real Server 上必须配置VIP且需要隐藏起来,只有在响应客户端请求时才使用VIP作为源地址,除此之外并不使用此VIP。
1、集群节点和Director必须在同一个网络中;
2、RIP可以为公有地址,或私有地址;
3、Director仅处理所有进来的请求;
4、Real Server 不能以DIP作为网关,而是以公网上的某台路由器作为网关;
5、Director 不能再使用端口映射;
6、大多数操作系统可以被用来作为Real Server,windows除外;
实际生产环境中最常用的一种方式,优点:
LVS-DR模式可以处理比LVS-NAT更多的请求,支持数量100。
RIP 为公网地址,管理员可以远程连接Real Server来查看工作状态;
一旦Director 宕机,可以通过修改DNS记录将A记录指向RIP 继续向外提供服务;
IP tunneling (LVS-TUN ):
与DR的网络结构一样,但Director和Real Server可以在不同的网络当中,可以实现异地容灾的功能。DIP----->VIP 基于隧道来传输,在数据包外层额外封装了S:DIP D :RIP 的地址。
Director和Real Server 必须在同一个物理网络中;
RIP一定不能是私有地址;
Director只负责处理进来的数据包;
Real Server直接将数据包返回给客户端,所以Real Server默认网关不能是DIP,必须是公网上某个路由器的地址;
Director不能做端口重映射;
只有支持隧道协议的操作系统才能作为Real Server。
LVS集群调度算法:
固定调度算法:
按照某种既定的算法,不考虑实时的连接数予以分配。
1、Round-robin(RR)轮询:当新请求到达时候,从服务列表中选择一个Real Server,将请求重定向给这台Real Server。
2、Weighted round-robin(WRR)加权轮询:给每台Real Server分配一个权重/位列,权重越大,分到的请求数越多。
3、Destination hashing (DH)目标散列:来自于同一个IP地址的请求都被重定向到同一台Real Server上(保证目标地址不变)。
4、Source hashing(SH)源地址散列:Director必须确保响应的数据包必须通过请求数据包所经过的路由器或者防火墙(保证原地址不变)。
动态调度算法:
通过检查服务器上当前连接的活动状态来重新决定下一步调度方式该如何实现。
1、Lease Connection (LC) 最少连接 哪一个Real Server上的连接数少就将下一个连接请求定向到那台Real Server上去。 【算法:连接数=活动连接数*256+非活动连接数】
2、Weight Least-Connection(WLC) 加权最少连接 在最少连接的基础上给每台Real Server分配一个权重。 【算法:连接数=(活动连接数*256+非活动连接数)÷权重】 一种比较理想的算法。
3、Shortest Expected Delay (SED) 最短期望延迟 不再考虑非活动连接数
【算法:连接数=(活动连接数+1) *256 ÷权重】
4、Never Queue (NQ) 永不排队算法,对SED的改进,当新请求过来的时候不仅要取决于SED算法所得到的值,还要取决于Real Server上是否有活动连接。
5、Locality-Based Least-Connection (LBLC) 基于本地状态的最少连接,在DH算法的基础上还要考虑服务器上的活动连接数。
6、Locality-Based Least-Connection with Replication Scheduling (LBLCR) 带复制的基于本地的最少连接 LBLC算法的改进。
下面我们就来做一个基于LVS-NAT的负载均衡实验:
实验环境搭建:
Director :VIP192.168.0.127 桥接
DIP192.168.10.1 仅主机
Real Server 1:RIP 192.168.10.2 仅主机 网关指向:192.168.10.1
Real Server 2:RIP 192.168.10.3 仅主机 网关指向:192.168.10.1
Client:192.168.0.1 物理机
每台Real Server上分别安装有http服务。我们这里为了演示效果,每个http服务的页面不同。
Real Server 1
[root@station39 html]# ifconfig eth0 192.168.10.2
[root@station39 html]# route add default gw 192.168.10.1
Real Server 2
[root@station26 html]# ifconfig eth0 192.168.10.3
[root@station26 html]# route add default gw 192.168.10.1
Director :
[root@server27 ~]# ifconfig eth1 192.168.10.1
打开内核路由功能
[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
确保永久有效:
[root@server27 ~]# vim /etc/sysctl.conf
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
[root@server27 ~]# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 4294967295
kernel.shmall = 268435456
OK,准备工作已经就绪,下面开始实验的关键步骤:
[root@server27 ~]# yum install ipvsadm -y
使用步骤:1.定义服务 2 .为服务定义Real Server
[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s rr
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 rr
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.3 -m -w 5
-g, --gatewaying Use gatewaying (direct routing). This is the default.
-i, --ipip Use ipip encapsulation (tunneling).
-m, --masquerading Use masquerading (network access transla-tion, or NAT).
PS:在这里设定的权重对于RR算法来说并没有什么意义,我们只是为后面的实验而设定的。
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 rr
-> 192.168.10.3:80 Masq 5 0 16
-> 192.168.10.2:80 Masq 2 0 15
此时,我们使用物理机访问192.168.0.127就会发现页面交替变化,这是由RR算法的特性决定的。
我们改变为WRR算法试试:
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wrr
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 wrr
-> 192.168.10.3:80 Masq 5 0 86
-> 192.168.10.2:80 Masq 2 0 43
改变为LBLC算法试试:
LBLC:基于本地状态的最少连接,在DH算法的基础上还要考虑服务器上的活动连接数。
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s lblc
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 lblc
-> 192.168.10.3:80 Masq 5 0 112
-> 192.168.10.2:80 Masq 2 0 41
此时无论客户端怎么刷新,访问页面都不会改变。
保存规则:
ipvsadm -S >>/etc/sysconfig/ipvs-config == ipvsadm-save
ipvsadm -R < /etc/sysconfig/ipvs-config == ipvsadm-restore
Director routing (LVS-DR ):
PS:Director分发到Real Server的过程中,数据包的源地址和目标地址都没有发生改变,Director仅仅是将目标mac地址转换成某台Real Server的mac地址,源mac地址改为Director内网网卡的mac地址。
两个技术难题:
1 Real Server要避免对客户端发来的对VIP的arp地址解析请求;
解决方法
1) 修改内核的两个参数:arp_announce, arp_ignore。
arp_announce :定义不同级别:当ARP请求通过某个端口进来是否利用这个接口来回应。
0 - (default) Use any local address, configured on any interface.
利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;
1 - Try to avoid local addresses that are not in the target's subnet for this interface.
避免使用另外一个接口上的mac地址去响应ARP请求;
2 - Always use the best local address for this target.
尽可能使用能够匹配到ARP请求的最佳地址。
arp_ignore:当ARP请求发过来后发现自己正是请求的地址是否响应;
0 - (default): reply for any local target IP address, configured on any interface
利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;
1 - reply only if the target IP address is local address configured on the incoming
interface.
哪个接口上接受ARP请求,就从哪个端口上回应。
PS:对linux来说IP地址属于系统而不属于某个接口。
2) Red Hat 提供了arptables工具,利用arp防火墙也可以实现。
2 当Real Server内网网卡响应客户端请求时,要以VIP作为源地址,不能以RIP作为源地址。
解决方法:
添加一条路由:route add -host 192.168.0.127 dev lo:0使客户端访问VIP,就让VIP来响应客户端。这样避免了使用RIP作为源地址。
Director:VIP响应客户端请求;
DIP:与RIP彼此间实现arp解析,并将客户端的请求转发给Real Server。
实验环境搭建:
Director :eth0:0 VIP192.168.0.127
eth0 DIP192.168.0.10 桥接
Real Server 1: eth0 RIP 192.168.0.12 桥接
lo:0 VIP 192.168.0.127
Real Server 2: eth0 RIP 192.168.0.13 桥接
lo:0 VIP 192.168.0.127
Client:192.168.0.1 物理机
Real Server 1
[root@station39 ~]# vim /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
[root@station39 ~]# sysctl -p
[root@station39 ~]# ifconfig eth0 192.168.0.12/24
[root@station39 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@station39 ~]# route add -host 192.168.0.127 dev lo:0
Real Server 2
[root@station26 ~]# vim /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
[root@station26 ~]# sysctl -p
[root@station26 ~]# ifconfig eth0 192.168.0.13/24
[root@station26 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@station26 ~]# route add -host 192.168.0.127 dev lo:0
Director
[root@server27 ~]# ifconfig eth0 192.168.0.10/24
[root@server27 ~]# ifconfig eth0:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@server27 ~]# route add -host 192.168.0.127 dev eth0:0
[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@server27 ~]# ipvsadm -C
[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s wlc
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.12 -g -w 5
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.13 -g -w 8
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 wlc
-> 192.168.0.13:80 Route 8 0 18
-> 192.168.0.12:80 Route 5 0 11
PS:如果要保持访问的页面一致,我们可以另外准备一台服务器专门用来存放网页文件,然后通过NFS共享的方式挂载到Real Server的网页目录下,就可以实现真正的负载均衡了。
实现持久连接:
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wlc -p 3600
[root@server27 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.127:80 wlc persistent 3600
-> 192.168.0.13:80 Route 8 0 62
-> 192.168.0.12:80 Route 5 0 0
此时,你会发现无论访问页面怎么刷新都不会再改变,这就是LVS持久性。
LVS Persistence 持久性
尽管我们选择了LVS的分发方法,但是大多时候我们要保证返回给客户端的所有响应请求必须来自于同一台Real Server,这里我们就要用到LVS Persistence(持久性)。
当使用SSL会话的时候,我们常常期望只交换一次密钥就可以建立永久连接,因此,LVS持久性在SSL会话中经常被用到。
当使用LVS持久性的时候,Director在内部使用一个连接根据记录称之为“持久连接模板”来确保所有来自同一个客户端的请求被分发到同一台Real Server上。
LVS 持久性类型:PCC PPC PNMP 混合类型。
Persistent client connections (PCC), cause all services a client is accessing to persist. (Also called zero port connections.)
来自同一客户端所有服务的请求都被重定向到同一台Real Server上,以IP地址为准。
PCC是一个虚拟服务没有端口号(或者端口号为0),以"-p" 来标识服务。
缺陷:定向所有服务,期望访问不同的Real Server无法实现。
假设一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,就需要这样定义:
ipvsadm -A -t 192.168.0.220:0 -s rr -p
ipvsadm -a -t 192.168.0.220.3:0 -r 192.168.10.11 -m
ipvsadm -a -t 192.168.0.220:0 -r 192.168.10.11 -m
Persistent port connections (PPC), which cause a single service to persist.
来自同一服务的请求都被重定向到同一台Real Server上,以端口号为准。
例如:client---->LVS(80,22)------>RS1 client----->LVS(23)----->RS2
缺陷:期望访问不同的端口到同一台RS上,无法实现。
Persistent Netfilter Marked Packet persistence, which causes packets that have been marked with the iptables utility to persist.
根据iptables 的规则,将对于某类服务/几个不同端口的访问定义为一类。
先对某一特定类型的数据包打上标记,然后再将基于某一类标记的服务送到后台的Real Server上去,后台的Real Server 并不识别这些标记。
PS:在LVS-NAT的环境下做这个实验,由于前边的DR模型使用了网卡别名,所以并不适合这个实验。
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 2
[root@server27 ~]# ipvsadm -A -f 2 -s wlc -p 3600
[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.3 -m -w 5
将持久和防火墙标记结合起来就能够实现端口姻亲功能,只要是来自某一客户端的对某一特定服务(需要不同的端口)的访问都定义到同一台Real Server上去。
假设这样一种场景:一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,我们需要将其定义到同一台Real Server上,而其他的服务不受限制,我们可以这样做:
实验基于LVS-NAT的环境。
先做一个自签名的证书
Real Server 1:
[root@station39 ~]# cd /etc/pki/tls/certs/
[root@station39 ~]# cd /etc/pki/tls/certs/
[root@station39 certs]# make httpd.pem
[root@station39 certs]# mv httpd.pem /etc/httpd/
[root@station39 httpd]# yum install mod_ssl -y
[root@station39 httpd]# cd conf.d/
[root@station39 conf.d]# vim ssl.conf
SSLCertificateFile /etc/httpd/httpd.pem //** line 112
SSLCertificateKeyFile /etc/httpd/httpd.pem //** line 119
重启httpd 服务。
[root@station39 ~]# vim /etc/hosts
192.168.10.2 web1.a.com web1
Real Server 2 :
[root@station26 ~]# yum install mod_ssl -y
[root@station26 certs]# cd /etc/httpd
[root@station26 httpd]# make -C /etc/pki/tls/certs httpd.pem
[root@station26 httpd]# mv /etc/pki/tls/certs/httpd.pem ./
[root@station26 httpd]# cd conf.d/
[root@station26 conf.d]# vim ssl.conf
SSLCertificateFile /etc/httpd/httpd.pem //** line 112
SSLCertificateKeyFile /etc/httpd/httpd.pem //** line 119
重启httpd 服务。
[root@station26 ~]# vim /etc/hosts
192.168.10.3 web2.a.com web2
Director:
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 5
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 443 -j MARK --set-mark 5
[root@server27 ~]# ipvsadm -A -f 5 -s wlc -p
[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.3 -m -w 5
OK,修改windows客户端的C:\WINDOWS\system32\drivers\etc\hosts 文件,添加两条名称解析记录:
192.168.0.127 web1.a.com
192.168.0.127 web2.a.com
此时物理机访问192.168.0.127无论是http还是https 服务都会被定义到同一台Real Server上去。
这里我们是为了演示实验的效果,使用的不同的证书,不同的页面。真实的生产环境中要求这些必须是一致的。
FTP connections (FTP connections require careful handling due to the complex nature of FTP connections).
PS:指定一个范围,将范围内的端口打上标记。然后使VSFTPD在被动模式下不再使用随机端口,而是使用范围内的随机端口,从而实现FTP的负载均衡。
1 Limiting the port range for passive connections, you must also configure the VSFTP server to use a matching port range:
vim /etc/vsftpd.conf:
pasv_min_port=10000
pasv_max_port=20000
2 You must also control the address that the server displays to the client for passive FTP connections. In a NAT routed LVS system, add the following line to /etc/vsftpd.conf to override the real server IP address to the VIP, which is what the client sees upon connection. For example:
pasv_address=n.n.n.n
3 iptables定义端口姻亲:
iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 21 -j MARK --set-mark 21
iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 10000:20000 -j MARK --set-mark 21
Expired persistence, which is used internally by the Director to expire connection tracking entries when the persistent connection template expires.