# lvs负载均衡集群 client --->负载均衡器--->web服务器(nginx apache) nginx也可以当作负载均衡器 7层负载 需要在反向代理的配置基础上添加配置 负载均衡 单个服务器性能有上限 单台服务器提供的服务 本身是一个单故障节点 常见的负载均衡都有哪些(面试题) 软件负载均衡 4层 lvs 7层 nginx haproxy 硬件负载均衡 f5(BIGIP) radware 负载均衡的作用是什么?(面试题) 流量分发 后端的单个服务器可以降低配置 防止单节点故障 正向代理 缓存 提升客户端上网的速度 client --- >正向代理---> 百度 /---------------------------/ /------/ 客户端网络 外网 透明代理 做访问控制 限制客户端的上网行为 client --- >透明代理---> 百度 /---------------------------/ /------/ 客户端网络 外网 不允许客户端访问.mp4结尾的网站 .mp3 反向代理 隐藏真正的服务器的Ip 利用代理的缓存功能加快客户端访问服务器的速度 client --- >反向代理---> 百度 /------/ /-----------------------------/ 客户端网络 外网 负载均衡 load balance 给负载做均衡 把负载均衡到后端不同的服务器上 流量分流 可以避免单故障节点 后端服务器代码可以轮流下线更新 负载均衡器是一个单故障节点 nginx haproxy 7层负载均衡 因为他主要使用的是7层协议 http OSI模型的第7层 应用层 nginx 4层负载均衡 lvs 4层负载均衡(2 3层) 硬件4层负载均衡:BIG-IP(F5) RADWARE **lvs模式分类** ```bash nat模式 后端服务器支持数量10-20台 使用最少两个网段 3层负载均衡 dr模式 直接路由 重点 后端服务器支持数量100+台 使用一个网段 2层负载均衡 tunnel 隧道模式 后端服务器支持数量100左右 异地负载均衡 realserver必须使用公网Ip,还得需要服务器支持ip隧道协议 full-nat **nat模式数据流向** 流量从client-->dr-->rs rs-->dr-->client client cip ↑↓ ↑↓------->vip dr ↑↓------->dip \-------------- ↑↓ ↓ rs1 rs2----->rip **dr模式数据流向** 流量从client-->dr-->rs rs-->client →→→ client cip23 ↑ ↓ ↑ ↓------->vip 30 ↑ **dr** ↑ ↓------->dip 20 ↑ +----------+ ←←←↓ ↓ **rs1** **rs2**----->rip 21 22 设置vip30/32 设置vip30/32 源IP 目标IP 30 源MAC 目标MAC 21 路由数据包特点:源Ip不会发生变化 目标IP发生变化 源和目标MAC都会发生变化 源地址 目标地址 ## dr模式工作原理 数据链路层负载均衡 顾名思义,数据链路层负载均衡是指在通信协议的数据链路层修改mac地址进行负载均衡。 这种数据传输方式又称作三角传输模式,负载均衡数据分发过程中不修改IP地址,只修改目的mac地址,通过配置真实物理服务器集群所有机器虚拟IP和负载均衡服务器IP地址一致,从而达到不修改数据包的源地址和目的地址就可以进行数据分发的目的,由于实际处理请求的真实物理服务器IP和数据请求目的IP一致,不需要通过负载均衡服务器进行地址转换,可将相应数据包直接返回给用户浏览器,避免负载均衡服务器网卡带宽成为瓶颈。这种负载均衡方式又称作直接路由方式(DR)。 使用三角传输模式的链路层负载均衡时目前大型网站使用最广的一种负载均衡手段。在linux平台上最好的链路层负载均衡开源产品是LVS(linux virtual server) **配置dr模式需要解决的问题** 1.来回数据包不一致 1)在rs的lo网卡设置vip/32 2)在rs上拒绝arp回应 3)设置让更好的IP回应数据包 2.在同一台机器上出现两块同一网段的网卡,数据包出去的时候,谁的路由条目在上面,就走哪块网卡 **配置虚拟服务器步骤** route -n 查看vip两块ip下面的就是vip 同理上面就是dip(如果没有命令 yum -y install net-tools) ```bash # ipvsadm -A -t vip:80 -s rr # ipvsadm -a -t vip:80 -r rip1:80 -g //rip就是web服务器的ip # ipvsadm -a -t vip:80 -r rip2:80 -g # echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore //web服务器做 配置虚拟网卡 # echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce //和上同理 **dr模式问题详解** 1. 客户端要找vip访问80端口,因为是在同一个网段,所以发arp广播(255.255.255.255)找vip的mac地址通信 2. 因为有rs上也有vip,不能直接让rs上的vip回应客户端的广播,所以设置文件arp_ignore的内容为1,1的意思是如果发来的广播包里面目标地址不是我的"进口地址"-->也就是"eth0"(对应的是非进口地址本地回环接口lo),那我就不回应这个arp广播。 因为在同一个局域网内的同一个网段,解决IP地址冲突: ```bash # echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore ``` 3. 当dr的vip收到这个广播之后,回应mac地址,然后得到客户端发来的80端口请求,再通过lvs分发到一个rs 4. 那么dr如何分发到一个rs? dip发出arp广播询问rs的ip地址所对应的mac地址,然后发出一个目标ip为rs_vip,目标mac为rs_eth0_mac的包到rs 过程中lvs会修改数据包mac地址 : dr的dip发数据包给realserver,数据头里面需要目标IP为vip,MAC地址为rip所在网卡的MAC 我们必须保证dr是从dip发包给rip: 查看dr机器的路由条目,哪块网卡的路由在上面,哪块网卡的IP地址就当DIP 5. 这个rs必须要使用他lo设置的vip把回应包发出去(这样client收到之后一看源地址是vip,他就会相信这是正确的地址发来的包 6. 那么怎样让rs使用lo的vip而不使用eth0? 设置arp_announce文件的内容为2, 2的意思是使用本机最好的本地IP地址把回应包发出去 dr模式里需要realserver直接返回数据给客户端,但是客户端默认情况下不接收realserver返回的数据,因为client发出的数据包是给vip的,所以在realserver上也设置vip,想办法让vip返回数据给客户端 ```bash #echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce ``` 7. 最后怎么算是最好的本地IP地址? 同一个网段下,使用可变长度子网掩码最长的IP地址被认为是好IP,因为他更精确 ## dr模式实验 环境:3台机器 首先确实dr上面vip route -n (yum -y install net-tools) [root@fxs ~]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default gateway 0.0.0.0 UG 100 0 0 ens36 //dip default gateway 0.0.0.0 UG 101 0 0 ens33 //位于第二位vip 192.168.17.0 0.0.0.0 255.255.255.0 U 100 0 0 ens36 192.168.17.0 0.0.0.0 255.255.255.0 U 101 0 0 ens33 web服务器操作 ```bash 10.0.0.20 dr1 负载均衡器 10.0.0.21 rs1 web1 10.0.0.22 rs2 web2 ``` 1、两个rs上部署web服务 ```bash # yum install nginx -y 注意把两台服务器的主页内容修改为不同的内容 # systemctl start nginx ``` 2、给两个web服务器的lo网卡设置子网掩码为32位vip (在这之前先确定一下谁是VIP) ```bash rs1: # ifconfig lo:0 10.0.0.30/32 //数字0不是固定的 或者 # ip a a 10.0.0.30/32 dev lo:0 rs2: # ifconfig lo:0 10.0.0.30/32 ``` 3、为了让vip发包出去且忽略arp响应 ,给两个web服务器设置内核参数 ```bash # echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce # echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 4、保证dr这台机器数据包是从dip发出去的 如何判断:谁的路由条目在上面,谁就是dip,另一个就是vip 5、在dr上设置lvs路由条目(临时生效) dr上面操作 # yum install ipvsadm -y # ipvsadm -A -t 10.0.0.30:80 -s rr # ipvsadm -a -t 10.0.0.30:80 -r 10.0.0.21:80 -g # ipvsadm -a -t 10.0.0.30:80 -r 10.0.0.22:80 -g -A 添加virtual server -t 指定使用tcp协议 -s 指定调度策略为rr 轮询 round robin -a 添加realserver -r 指定realserver是谁 # ipvsadm -C 清除策略 ``` **让配置永久生效** ```bash # ipvsadm-save > /etc/sysconfig/ipvsadm # systemctl enable ipvsadm ``` **特别注意:** **1.不要在dr上访问vip,可能访问不成功** **2.新版本lvs的持久连接默认生效且修改太短时间不生效。也就是只要是同一个客户端ip,在一定时间内,他总会被分配到同一个后端服务器。** **命令选项解释** ```bash * -A --add-service 在内核的虚拟服务器表中添加一条新的虚拟服务器记录。也就是增加一台新的虚拟服务器。 -E --edit-service 编辑内核虚拟服务器表中的一条虚拟服务器记录。 -D --delete-service 删除内核虚拟服务器表中的一条虚拟服务器记录。 * -C --clear 清除内核虚拟服务器表中的所有记录。 -R --restore 恢复虚拟服务器规则 * -S --save 保存虚拟服务器规则,输出为-R 选项可读的格式 * -a --add-server 在内核虚拟服务器表的一条记录里添加一条新的真实服务器记录。也就是在一个虚拟服务器中增加一台新的真实服务器 -e --edit-server 编辑一条虚拟服务器记录中的某条真实服务器记录 -d --delete-server 删除一条虚拟服务器记录中的某条真实服务器记录 * -L|-l --list 显示内核虚拟服务器表 * -Z --zero 虚拟服务表计数器清零(清空当前的连接数量等) --set tcp tcpfin udp 设置连接超时值 --start-daemon 启动同步守护进程。他后面可以是master 或backup,用来说明LVS Router 是master 或是backup。在这个功能上也可以采用keepalived 的VRRP 功能。 --stop-daemon 停止同步守护进程 * -h --help 显示帮助信息 * -p --persistent [timeout] 持久稳固的服务(持久性连接)。这个选项的意思是来自同一个客户的多次请求,将被同一台真实的服务器处理。timeout 的默认值为300 秒。 * -t --tcp-service service-address 说明虚拟服务器提供的是tcp 的服务[vip:port] or [real-server-ip:port] -f --fwmark-service fwmark 说明是经过iptables 标记过的服务类型。 -u --udp-service service-address 说明虚拟服务器提供的是udp 的服务[vip:port] or [real-server-ip:port] * -s --scheduler scheduler 使用的调度算法,有这样几个选项 rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,默认的调度算法是: wlc. -M --netmask netmask persistent granularity mask * -r --real-server server-address 真实的服务器[Real-Server:port] * -g --gatewaying 指定LVS 的工作模式为直接路由模式(也是LVS 默认的模式) -i --ipip 指定LVS 的工作模式为隧道模式 -m --masquerading 指定LVS 的工作模式为NAT 模式 * -w --weight weight 真实服务器的权值 --mcast-interface interface 指定组播的同步接口 * -c --connection 显示LVS 目前的连接 如:ipvsadm -L -c --timeout 显示tcp tcpfin udp 的timeout 值 如:ipvsadm -L --timeout --daemotcpdump -i ens33 tcp and port 80 -v -nnn 显示同步守护进程状态 * --stats 显示统计信息 --rate 显示速率信息 --sort 对虚拟服务器和真实服务器排序输出 * -n --numeric 输出IP地址和端口的数字形式 ``` **如果出现问题可选择采用抓包方式查看数据走向查找问题** ```bash # tcpdump -i ens33 tcp and port 80 -v -nn -i 指定网卡 tcp 抓tcp协议的数据包 port 指定要抓哪个端口的包 -v 显示详细信息 -nn 以数字的形式显示ip和端口 ``` **ip命令基本使用** 查看IP ```bash #ip a #ip a l dev ens33 ``` 添加IP ```bash # ip a a 192.168.1.8/24 dev ens33 ``` 删除IP ```bash # ip a d 192.168.1.8/24 dev ens33 ``` ## lvs调度算法(面试题) 1. 轮询调度(Round Robin)(简称rr) 调度器通过"轮叫"调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。 2. 加权轮询(Weighted Round Robin)(简称wrr) 调度器通过"加权轮叫"调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器能处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。 a 3 1 b 6 2 3. 最少连接(Least Connections)(LC) 调度器通过"最少连接"调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用 "最小连接" 调度算法可以较好地均衡负载。 4. 加权最少链接(Weighted Least Connections)(WLC) 在集群系统中的服务器性能差异较大的情况下,调度器采用 "加权最少链接"调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。 5. 基于局部性的最少链接(Locality-Based Least Connections)(LBLC) "基于局部性的最少链接"调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。**该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器**;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用"最少链接" 的原则选出一个可用的服务器,将请求发送到该服务器。 **A B C D E** *A1 B1 C1 D1 E1* A2 B2 C2 D2 E2 1 2 3 6. 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication)(LBLCR) “带复制的基于局部性最少链接”调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。**它与LBLC算法的不同之处是它要维护从一个目标 IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射**。该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。 7. 最短期望的延迟(Shortest Expected Delay Scheduling SED)(SED) 基于wlc算法。这个必须举例来说了 A B C 1 2 3 1 2 3 ABC三台机器分别权重123 ,连接数也分别是123。那么如果使用WLC算法的话一个新请求进入时它可能会分给 ABC中的任意一个。使用sed算法后会进行这样一个运算 A(1+1)/1 B(1+2)/2 C(1+3)/3 根据运算结果,把连接交给C。 注:前面的1是给所有连接数加1,后面的除数是权重 我本来负载就小,所以才连接数少,假如我这点负载再添加一个连接,我可能就挂了,但是你负载高的再添加1 个连接,挂的可能小就比较小 8. 最少队列调度(Never Queue Scheduling NQ)(NQ) 无需队列。如果有台 realserver的连接数=0就直接分配过去,不需要在进行sed运算 9. 目标地址散列(Destination Hashing)(DH) 特点是查找速度快 "目标地址散列"调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。 10.源地址散列(Source Hashing)(SH) "源地址散列"调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。 外翻: 目标地址散列调度(Destination Hashing Scheduling)算法 是针对目标IP地址的负载均衡,但它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。 目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。该算法的流程如下: **目标地址散列调度算法流程** 假设有一组服务器S = {S0, S1, ..., Sn-1},W(Si)表示服务器Si的权值, C(Si)表示服务器Si的当前连接数。ServerNode[]是一个有256个桶(Bucket)的 Hash表,一般来说服务器的数目会小于256,当然表的大小也是可以调整的。 算法的初始化是将所有服务器顺序、循环地放置到ServerNode表中。若服务器的 连接数目大于2倍的权值,则表示服务器已超载。 n = ServerNode[hashkey(dest_ip)]; if ((n is dead) OR (W(n) == 0) OR (C(n) > 2*W(n))) then return NULL; return n; 在实现时,我们采用素数乘法Hash函数,通过乘以素数使得散列键值尽可能地达到较均匀的分布。所采用的素数乘法Hash函数如下: **素数乘法Hash函数** static inline unsigned hashkey(unsigned int dest_ip) { return (dest_ip* 2654435761UL) & HASH_TAB_MASK; } 其中,2654435761UL是2到2^32 (4294967296)间接近于黄金分割的素数, (sqrt(5) - 1) / 2 = 0.618033989 2654435761 / 4294967296 = 0.618033987 源地址散列调度(Source Hashing Scheduling)算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法 的相同。它的算法流程与目标地址散列调度算法的基本相似,除了将请求的目标IP地址换成请求的源IP地址,所以这里不一一叙述。 在实际应用中,源地址散列调度和目标地址散列调度可以结合使用在防火墙集群中,它们可以保证整个系统的唯一出入口。 ===================================== [散列表](http://baike.baidu.com/view/1320746.htm)(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的[数据结构](http://baike.baidu.com/view/9900.htm)。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做[散列函数](http://baike.baidu.com/view/131153.htm),存放记录的[数组](http://baike.baidu.com/view/209670.htm)叫做[散列表](http://baike.baidu.com/view/1320746.htm)。给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。 ## 阿里云负载均衡 alb application load balance http https grpc slb server load balance 几乎所有的应用都可以