最近在思考物联网平台的架构,然后之前对IM系统又很感兴趣,就想着一台服务器能连接的客户端也是有限的,那如果客户端突破这个限制了呢?所以自然而然就想到了负载均衡,比如Gateway、Nginx等等,有些不可以实现,有些可以实现,最终经过比较发现LVS可能对服务器集群的压力小一些(但是会暴露真实服务器的IP地址,如果有大神有更好的方案,感谢指点一下)。
然后考虑到服务器可能不是都在一个局域网的,例如异地灾备之类的,所以LVS的NET模式和DR模式就不符合我们的需求了。由此先拿TUN模式试试水。
LVS-TUN模式
在TUN工作模式下,Client向Director server 发送请求报文,报文到达Director 内核空间不修改请求报文的ip首部,而是通过在原有ip首部[CIP-VIP]之外,再封装一个ip首部[DIP-RIP],RS收到报文后发现是自己的IP地址,就会将报文接受下来,拆除最外层的IP后,会发现里面还有一层IP首部,而且目标地址是自己的lo接口VIP,那么此时RS开始处理此请求,处理完成滞后,通过lo接口送给eth0网卡,然后向外传递。此时的源IP地址为VIP,目标IP为CIP。
LVS-TUN模型运行原理
TUN模式工作流程
1、当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP 。
2、 PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
3、IPVS比对数据包请求的服务是否为集群服务,若是,在请求报文的首部再次封装一层IP报文,封装源IP为为DIP,目标IP为RIP。然后发至POSTROUTING链。 此时源IP为DIP,目标IP为RIP
4、POSTROUTING链根据最新封装的IP报文,将数据包发至RS(因为在外层封装多了一层IP首部,所以可以理解为此时通过隧道传输)。 此时源IP为DIP,目标IP为RIP
5、RS接收到报文后发现是自己的IP地址,就将报文接收下来,拆除掉最外层的IP后,会发现里面还有一层IP首部,而且目标是自己的lo接口VIP,那么此时RS开始处理此请求,处理完成之后,通过lo接口送给eth0网卡,然后向外传递。 此时的源IP地址为VIP,目标IP为CIP
TUN模型特点
1、RIP、VIP、DIP全是公网地址
2、RS的网关不会也不可能指向DIP
3、所有的请求报文经由Director Server,但响应报文必须不能进过Director Server
4、不支持端口映射,
5、RS的系统必须支持隧道
LVS调度算法
1.四种静态算法,不考虑后端服务器实际负载情况:
-
RR
根据规则依次论调,不考虑RS的性能。轮到谁就转发给谁。 -
WRR
加权轮询,加入了weight(权重),可以根据RS的性能为其设置权重值,权重越大功能越强,但是无法发现当前的服务器的运行情况如何。 -
DH
目标地址hash,适用于前端是一个director后端是几个缓存服务器的情况,当客户端第一次访问到的是RS1的时候,DH这种算法能保证在客户端刷新后还是访问的RS1。 -
SH
源地址hash,用于保证响应的报文和请求的报文是同一个路径。
2.六种动态算法,考虑后端服务器当前负载后再进行分配:
-
LC
leastconnection,当一个用户请求过来的时候,Director会计算一下哪台RS的连接数最小,那么这台RS就获得了下次响应客户端请求的机会,计算的方法Overhead=active*256+inactive,如果两者的结果是相同的则从LVS中的规则依次往下选择RS。这种算法也是不考虑服务器的性能的。 -
WLC
这个就是加了权重的LC,考虑了RS的性能,即性能好的就给的权重值大一些,性能差的给的权重值小一些。缺点就是如果Overhead相同,则会按规则表中的顺序,由上而下选择RS,Overhead=(active*256+inactive)/weight -
SED
就是对WLC的情况的补充,Overhead=(active+1)*256/weight,加1,就是为了让其能够比较出大小。 -
NQ
即neverqueue,基本和SED相同,避免了SED当中的性能差的服务器长时间被空闲的弊端,它是将第一个请求给性能好的服务器,第二个请求一定是给空闲的服务器不论它的性能的好与坏。之后还是会把请求给性能好的服务器。 -
LBLC
它就是动态DH和LC的组合,适用于cache集群,对于从来没有来过的那些新的请求会分给当前连接数较少的那台服务器。 -
LBLCR
带有复制功能的LBLC,它的适用场景这里举例说明一下,比如说现在有RS1和RS2,第一次访问RS1的5个请求第二次又来了,理所
应到Director将会将其交给RS1,而此时在RS2是非常闲的,所以此时最好的处理方法就是可以将后来的这5个请求分别交给RS1和RS2,所以此时就需要把客户端第一次请求的资源复制下来。(特殊情况)
配置实例
服务器 | IP1 | IP2 |
---|---|---|
服务器DR | 172.16.69.15/24 | 172.16.29.6/24 |
服务器B | 172.16.197.3/24 | |
服务器C | 192.168.134.5/24 |
调度服务器 Director
ipvsadm -C
ipvsadm -A -t 172.16.29.6:9001 -s rr
ipvsadm -a -t 172.16.29.6:9001 -r 172.16.197.3:9001 -i
ipvsadm -a -t 172.16.29.6:9001 -r 192.168.134.5:9001 -i
echo 1 > /proc/sys/net/ipv4/ip_forward
vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
vi /etc/sysconfig/network-scripts/ifcfg-ens34
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens34
UUID=8fd48a4d-b484-4acb-aa27-5bc7939f28f0
DEVICE=ens34
ONBOOT=yes
IPADDR="172.16.29.6"
NETMASK="255.255.255.0"
GATEWAY="172.16.29.6"
systemctl restart network
后端服务器 RS1、RS2
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="dhcp"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
DEVICE="ens33"
ONBOOT="yes"
modprobe ipip
ifconfig tunl0 172.16.29.6 netmask 255.255.255.255 up
systemctl restart network
vi /etc/sysctl.conf
net.ipv4.conf.tunl0.rp_filter = 0
net.ipv4.conf.tunl0.arp_ignore = 1
net.ipv4.conf.tunl0.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
sysctl -p
Linux的rp_filter用于实现反向过滤技术,也即uRPF,它验证反向数据包的流向,以避免伪装IP攻击。然而,在LVS TUN 模式中,数据包是有问题的,因为从real server ens33出去的IP数据包的源IP地址应该为RIP,而不是VIP地址。所以必须关闭这一项功能。
检验结果WEB和TCP Server(截图的地址原来是在局域网的基础上配置的TUN模式,所以用的还是局域网地址,但是不影响确认配置生效)
这里断开再连接会轮询到另外一台机器上