因公司进行数据搜集业务量比较大,单台服务器无法承受如此大的压力,机房所有的服务器都是配置的内网IP,在防火墙做的nat映射,这种情况下我们搭建lvs-dr模型就比较方便了,所以选择了DR模型,减少负载均衡器的负担。
一、LVS简介
LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分,在Linux2.4内核以前,使用LVS时必须要重新编译内核以支持LVS功能模块,但是从Linux2.4内核以后,已经完全内置了LVS的各个功能模块,无需给内核打任何补丁,可以直接使用LVS提供的各种功能。
使用LVS技术要达到的目标是:通过LVS提供的负载均衡技术和Linux操作系统实现一个高性能、高可用的服务器群集,它具有良好可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。
LVS自从1998年开始,发展到现在已经是一个比较成熟的技术项目了。可以利用LVS技术实现高可伸缩的、高可用的网络服务,例如WWW服务、Cache服务、DNS服务、FTP服务、MAIL服务、视频/音频点播服务等等,有许多比较著名网站和组织都在使用LVS架设的集群系统,例如:Linux的门户网站(www.linux.com)、向RealPlayer提供音频视频服务而闻名的Real公司(www.real.com)、全球最大的开源网站(sourceforge.net)等。
二、 LVS体系结构
使用LVS架设的服务器集群系统有三个部分组成:最前端的负载均衡层,用Load Balancer表示,中间的服务器群组层,用Server Array表示,最底端的数据共享存储层,用Shared Storage表示,在用户看来,所有的内部应用都是透明的,用户只是在使用一个虚拟服务器提供的高性能服务。
LVS体系结构如图1所示:
LVS的各个层次的详细介绍:
● Load Balancer层:位于整个集群系统的最前端,有一台或者多台负载调度器(Director Server)组成,LVS模块就安装在Director Server上,而Director的主要作用类似于一个路由器,它含有完成LVS功能所设定的路由表,通过这些路由表把用户的请求分发给Server Array层的应用服务器(Real Server)上。同时,在Director Server上还要安装对Real Server服务的监控模块Ldirectord,此模块用于监测各个Real Server服务的健康状况。在Real Server不可用时把它从LVS路由表中剔除,恢复时重新加入。
● Server Array层:由一组实际运行应用服务的机器组成,Real Server可以是WEB服务器、MAIL服务器、FTP服务器、DNS服务器、视频服务器中的一个或者多个,每个Real Server之间通过高速的LAN或分布在各地的WAN相连接。在实际的应用中,Director Server也可以同时兼任Real Server的角色。
● Shared Storage层:是为所有Real Server提供共享存储空间和内容一致性的存储区域,在物理上,一般有磁盘阵列设备组成,为了提供内容的一致性,一般可以通过NFS网络文件系统共享数 据,但是NFS在繁忙的业务系统中,性能并不是很好,此时可以采用集群文件系统,例如Red hat的GFS文件系统,oracle提供的OCFS2文件系统等。
从整个LVS结构可以看出,Director Server是整个LVS的核心,目前,用于Director Server的操作系统只能是Linux和FreeBSD,linux2.6内核不用任何设置就可以支持LVS功能,而FreeBSD作为 Director Server的应用还不是很多,性能也不是很好。对于Real Server,几乎可以是所有的系统平台,Linux、windows、Solaris、AIX、BSD系列都能很好的支持。
三、LVS类型及特点
NAT:地址转换
● 集群节点跟director必须在同一个IP网络中;
● RIP通常是私有地址,仅用于各集群节点间的通信;
● director位于client和real server之间,并负责处理进出的所有通信;
● realserver必须将网关指向DIP;
● 支持端口映射;
● realserver可以使用任意OS;
● 较大规模应该场景中,director易成为系统瓶颈;
DR:直接路由
● 集群节点跟director必须在同一个物理网络中;
● RIP可以使用公网地址,实现便捷的远程管理和监控;
● director仅负责处理入站请求,响应报文则由realserver直接发往客户端;
● realserver不能将网关指向DIP;
● 不支持端口映射;
TUN:IP隧道
● 集群节点可以跨越Internet;
● RIP必须是公网地址;
● director仅负责处理入站请求,响应报文则由realserver直接发往客户端;
● realserver网关不能指向director;
● 只有支持隧道功能的OS才能用于realserver;
● 不支持端口映射;
四、LVS调度方法
静态调度:
● rr(round robin):轮询调度,轮叫调度
轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。【提示:这里是不考虑每台服务器的处理能力】
● wrr(weight round robin):加权(以权重之间的比例实现在各主机之间进行调度)
由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。
● sh(source hashing):源地址散列。主要实现会话绑定,能够将此前建立的session信息保留了
源地址散列调度算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的并且没有超负荷,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。它的算法流程与目标地址散列调度算法的基本相似,除了将请求的目标IP地址换成请求的源IP地址,所以这里不一个一个叙述。
● Dh(destination hashing):目标地址散列。把同一个IP地址的请求,发送给同一个server。
目标地址散列调度算法也是针对目标IP地址的负载均衡,它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
动态调度:
● lc(least connection):最少连接
最少连接调度算法是把新的连接请求分配到当前连接数最小的服务器,最小连接调度是一种动态调度短算法,它通过服务器当前所活跃的连接数来估计服务器的负载均衡,调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1,当连接中止或超时,其连接数减一,在系统实现时,我们也引入当服务器的权值为0时,表示该服务器不可用而不被调度。
简单算法:active*256+inactive(谁的小,挑谁)
● wlc(weighted least-connection scheduling):加权最少连接。
加权最小连接调度算法是最小连接调度的超集,各个服务器用相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权限,加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。
简单算法:(active*256+inactive)/weight【(活动的连接数+1)/除以权重】(谁的小,挑谁)
● sed(Shortest Expected Delay):最短期望延迟
基于wlc算法
简单算法:(active+1)*256/weight 【(活动的连接数+1)*256/除以权重】
● nq(never queue):永不排队(改进的sed)
无需队列,如果有台realserver的连接数=0就直接分配过去,不需要在进行sed运算。
● LBLC(Locality-Based Least Connection):基于局部性的最少连接
基于局部性的最少连接算法是针对请求报文的目标IP地址的负载均衡调度,不签主要用于Cache集群系统,因为Cache集群中客户请求报文的布标IP地址是变化的,这里假设任何后端服务器都可以处理任何请求,算法的设计目标在服务器的负载基本平衡的情况下,将相同的目标IP地址的请求调度到同一个台服务器,来提高个太服务器的访问局部性和主存Cache命中率,从而调整整个集群系统的处理能力。
基于局部性的最少连接调度算法根据请求的目标IP地址找出该目标IP地址最近使用的RealServer,若该Real Server是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
● LBLCR(Locality-Based Least Connections withReplication):带复制的基于局部性最少链接
带复制的基于局部性最少链接调度算法也是针对目标IP地址的负载均衡,该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
五、ipvsadm的用法
1、Ipvsadm常用的语法和格式如下:
ipvsadm -A|E -t|u|f virutal-service-address:port [-s scheduler] [-p [timeout]] [-M netmask] ipvsadm -D -t|u|f virtual-service-address ipvsadm -C ipvsadm -R ipvsadm -S [-n] ipvsadm -a|e -t|u|f virtual-service-address:port -r real-server-address:port [-g|i|m] [-w weight] ipvsadm -d -t|u|f virtual-service-address -r real-server-address ipvsadm -L|l [options] ipvsadm -Z [-t|u|f virtual-service-address] ipvsadm --set tcp tcpfin udp ipvsadm –h
其中:
virtual-service-address:是指虚拟服务器的IP地址,本文是10.0.0.88
real-service-address:是指Real Server的IP地址,本文是10.0.0.9/20/21
scheduler:指定调度算法
2、ipvsadm命令选项详细含义
-A (--add-service) 在内核的虚拟服务器列表中添加一条新的虚拟IP记录。也就是增加一台新的虚拟服务器。虚拟IP也就是虚拟服务器的IP地址。
-E (--edit-service) 编辑内核虚拟服务器列表中的一条虚拟服务器记录
-D (--delete-service) 删除内核虚拟服务器列表中的一条虚拟服务器记录
-C (--clear) 清除内核虚拟服务器列表中的所有记录
-R (--restore) 恢复虚拟服务器规则
-S (--save) 保存虚拟服务器规则,输出为-R 选项可读的格式
-a (--add-server) 在内核虚拟服务器列表的一条记录里添加一条新的Real Server记录。也就是在一个虚拟服务器中增加一台新的Real Server
-e (--edit-server) 编辑一条虚拟服务器记录中的某条Real Server记录
-d (--delete-server) 删除一条虚拟服务器记录中的某条Real Server记录
-L|-l –list 显示内核中虚拟服务器列表
-Z (--zero) 虚拟服务器列表计数器清零(清空当前的连接数量等)
--set tcp tcpfin udp 设置连接超时值
-t 说明虚拟服务器提供的是tcp服务,此选项后面跟如下格式:
[virtual-service-address:port] or [real-server-ip:port]
-u 说明虚拟服务器提供的是udp服务,此选项后面跟如下格式:
[virtual-service-address:port] or [real-server-ip:port]
-f fwmark 说明是经过iptables标记过的服务类型
-s 此选项后面跟LVS使用的调度算法
有这样几个选项: rr|wrr|lc|wlc|lblc|lblcr|dh|sh
默认的调度算法是: wlc
-p [timeout] 在某个Real Server上持续的服务时间。也就是说来自同一个用户的多次请求,将被同一个Real Server处理。此参数一般用于有动态请求的操作中,timeout 的默认值为300 秒。例如:-p 600,表示持续服务时间为600秒。
-r 指定Real Server的IP地址,此选项后面跟如下格式:
[real-server-ip:port]
-g (--gatewaying) 指定LVS 的工作模式为直接路由模式(此模式是LVS 默认工作模式)
-i (-ipip) 指定LVS 的工作模式为隧道模式
-m (--masquerading) 指定LVS 的工作模式为NAT模式
-w (--weight) weight 指定Real Server的权值
-c (--connection) 显示LVS目前的连接信息 如:ipvsadm -L -c
-L --timeout 显示“tcp tcpfin udp”的timeout值,如:ipvsadm -L --timeout
-L --daemon 显示同步守护进程状态,例如:ipvsadm -L --daemon
-L --stats 显示统计信息,例如:ipvsadm -L --stats
-L --rate 显示速率信息,例如:ipvsadm -L --rate
-L --sort 对虚拟服务器和真实服务器排序输出,例如:ipvsadm -L --sort
注释:左边括弧中的内容为ipvsadm每个选项的长格式表示形式,linux命令选项中,有长格式和短格式,短格式的选项用的比较多,实际应用中可以用括弧中的长格式替代短格式,例如,可以用“ipvsadm --clear”代替“ipvsadm -C”。
3、举例
ipvsadm -A -t 10.0.0.88:80 -s rr -p 600
以上表示在内核的虚拟服务器列表中添加一条10.0.0.88的虚拟服务器记录,并且指定此虚拟服务器的服务端口为80,然后指定此虚拟服务器的调度策略为轮询调度,并且在每个real server上的持续服务时间为600秒,即10分钟。
ipvsadm -E -t 10.0.0.88:80 -s wlc
以上表示在内核的虚拟服务器列表中修改了调度算法,改为调度策略wlc,即加权最少链接算法。
ipvsadm -a -t 10.0.0.88:80 -r 10.0.0.9:80 -g ipvsadm -a -t 10.0.0.88:80 -r 10.0.0.20:80 -g
以上两条设置表示在虚拟服务器10.0.0.88中添加两条新的Real Server记录,两个Real Server的IP分别为10.0.0.9和10.0.0.20,参数“-g”指定了虚拟服务器的工作模式为直接路由模式,即DR模式。
这样设置完毕后,当用户访问10.0.0.88的80服务时,LVS会根据设置的调度策略和路由模式将请求分配到10.0.0.9以及10.0.0.20的80端口。
ipvsadm -d -t 10.0.0.88:80 -r 10.0.0.9:80
删掉集群中的一个realserver。
ipvsadm -e -t 10.0.0.88:80 -r 10.0.0.9:80 -g -w 3
修改10.0.0.9的权重为3
防火墙标记:
iptables -t mangle -A PREROUTING -d VIP -p tcp --dport CS_Port -j MARK --set-mark # (0-99)
定义集群服务:
ipvsadm -A -f # -s wrr
五、下面我们以LVS-DR模型进行安装配置
1、服务器IP分配
服务器 |
IP | VIP | 系统 |
Director | 10.0.0.12 | 10.0.0.88 | CentOS 6.x X64 |
Realserver1 | 10.0.0.9 | 10.0.0.88 | CentOS 6.x X64 |
Realserver2 | 10.0.0.20 | 10.0.0.88 |
CentOS 6.x X64 |
Realserver3 | 10.0.0.21 | 10.0.0.88 | CentOS 6.x X64 |
2、在Director Serve上安装IPVS管理软件
yum install ipvsadm -y
然后执行:
ipvsadm --help
如果看到帮助提示,表明IPVS已经成功安装。
七、LVS-Director的配置
这里提供一个Director的lvs脚本,大家直接运行此脚本即可配置好LVS,非常简单。
# cat /etc/init.c/lvs
#!/bin/bash # # LVS script for VS/DR # chkconfig: - 90 10 # description: LVS DR director . /etc/rc.d/init.d/functions # VIP=10.0.0.88 DIP=10.0.0.12 RIP1=10.0.0.9 RIP2=10.0.0.20 RIP3=10.0.0.21 PORT=80 RSWEIGHT1=2 RSWEIGHT2=5 RSWEIGHT3=5 # case "$1" in start) /sbin/ifconfig eth0:0 $VIP up /sbin/route add -host $VIP dev eth0:0 # Since this is the Director we must be able to forward packets echo 1 > /proc/sys/net/ipv4/ip_forward # Clear all iptables rules. /sbin/iptables -F # Reset iptables counters. /sbin/iptables -Z # Clear all ipvsadm rules/services. /sbin/ipvsadm -C # Add an IP virtual service for VIP 192.168.0.219 port 80 # In this recipe, we will use the round-robin scheduling method. # In production, however, you should use a weighted, dynamic scheduling method. /sbin/ipvsadm -A -t $VIP:80 -s wrr # Now direct packets for this VIP to # the real server IP (RIP) inside the cluster /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -g -w $RSWEIGHT1 /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -g -w $RSWEIGHT2 /sbin/ipvsadm -a -t $VIP:80 -r $RIP3 -g -w $RSWEIGHT3 /sbin/ipvsadm --set 11 15 300 /bin/touch /var/lock/subsys/ipvsadm &> /dev/null ;; stop) # Stop forwarding packets echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm /sbin/ipvsadm -C # Bring down the VIP interface /sbin/ifconfig eth0:0 down /sbin/route del $VIP /bin/rm -f /var/lock/subsys/ipvsadm echo "ipvs is stopped..." ;; status) if [ ! -e /var/lock/subsys/ipvsadm ]; then echo "ipvsadm is stopped ..." else echo "ipvs is running ..." ipvsadm -L -n fi ;; *) echo "Usage: $0 {start|stop|status}" ;; esac
RealServer脚本:
# cat /etc/init.d/lvs-rs
#!/bin/bash # # Script to start LVS DR real server. # chkconfig: - 90 10 # description: LVS DR real server # . /etc/rc.d/init.d/functions VIP=10.0.0.88 host=`/bin/hostname` case "$1" in start) # Start LVS-DR real server on this machine. /sbin/ifconfig lo down /sbin/ifconfig lo up echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev lo:0 ;; stop) # Stop LVS-DR real server loopback device(s). /sbin/ifconfig lo:0 down echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce ;; status) # Status of LVS-DR real server. islothere=`/sbin/ifconfig lo:0 | grep $VIP` isrothere=`netstat -rn | grep "lo:0" | grep $VIP` if [ ! "$islothere" -o ! "isrothere" ];then # Either the route or the lo:0 device # not found. echo "LVS-DR real server Stopped." else echo "LVS-DR real server Running." fi ;; *) # Invalid entry. echo "$0: Usage: $0 {start|status|stop}" exit 1 ;; esac
在director和realserver各启动好上面的脚本服务,然后在director查看lvs状态
# ipvsadm -ln
# ipvsadm -Ln --stats //显示统计信息
# ipvsadm -L --rate //显示速率信息
七、LVS状态讲解
我们通过ipvsadm -ln可以查看到lvs的状态情况如下
[root@lvs1 ~]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.0.0.88:80 wrr -> 10.0.0.9:80 Route 2 3162 387 -> 10.0.0.10:80 Route 1 3906 28 -> 10.0.0.20:80 Route 5 8010 1011 -> 10.0.0.21:80 Route 6 9492 1215
ActiveConn是活动连接数,也就是tcp连接状态的ESTABLISHED。
InActConn是指除了ESTABLISHED以外所有的其它状态的tcp连接。
那既然这样,为什么从lvs里看的ActiveConn会比在真实机上通过netstats看到的ESTABLISHED高很多呢?问得好!这也是笔者一直迷惑而渐渐清晰的一个问题。原来lvs自身也有一个默认超时时间。可以用ipvsadm -L --timeout查看,默认是900 120 300,分别是TCP TCPFIN UDP的时间.也就是说一条tcp的连接经过lvs后,lvs会把这台记录保存15分钟,而不管这条连接是不是已经失效!所以如果你的服务器在15分钟以内有大量的并发请求连进来的时候,你就会看到这个数值直线上升。
其实很多时候,我们看lvs的这个连接数是想知道现在的每台机器的真实连接数吧?怎么样做到这一点呢?其实知道现在的ActiveConn是怎样产生的,做到这一点就简单了。举个例子:比如你的lvs是用来负载网站,用的模式是dr,后台的web server用的nginx。这时候一条请求过来,在程序没有问题的情况下,一条连接最多也就五秒就断开了。这时候你可以这样设置:ipvsadm --set 5 10 300。设置tcp连接只保持5秒中。如果现在ActiveConn很高你会发现这个数值会很快降下来,直到降到和你用nginx的status看当前连接数的时候差不多。你可以继续增加或者减小5这个数值,直到真实机的status连接数和lvs里的ActiveConn一致。
我自己设置的是ipvsadm --set 10 20 300
至此,在服务器上面运行上脚本即可,大家可能根据需要修改对应的一些IP,在这里演示效果我不在展示。