首先,负载均衡可分不同级别的负载:数据包级别均衡,tcp握手传输层级别,http的url应用层级别。
大型网站分层负载一般是先来一层lvs进行数据包级别的负载,不和client握手(四层),如下:
再来一层握手级别的负载用nginx(5w个并发,七层的反向代理),最后是tomcat计算层负载(一堆tomcat)。如下:
LVS负载均衡
参考链接:https://blog.csdn.net/weixin_40470303/article/details/80541639
CIP:客户端 VIP:负载均衡服务器 RIP:处理请求的真实服务器,
1、基于NAT的LVS模式负载均衡(基于3-4层的负载均衡,负载均衡服务器根据ip转发数据包)
简单理解,就是客户端的请求和响应全部通过负载均衡服务器。一个数据包请求来的时候的路径为:
CIP -> VIP -> RIP,返回的时候为:
RIP -> VIP -> CIP,
该模式即为基于NAT的模式,在请求到达VIP时,把目标地址换成RIP,原地址换成VIP。在请求从RIP返回VIP时,把目标地址换成CIP,把原地址换成VIP,这就需要一个CIP和RIP的映射关系。
总结:非对称,消耗算力,带宽成为瓶颈,要求,RIP的GW指向负载均衡服务器
2、基于DR的LVS负载均衡(负载均衡服务器根据mac转发数据包)
由于请求和响应往往数据量不同,例如请求可能只是一个简单的get,但服务器却要返回一堆html,css,js,图片等静态资源,所以数据上行和下行的流量不同,下行的流量会特别大。对于服务器来说,是上行的流量会特别大(家用宽带上行带宽往往比下行带宽小也是这个原因)。所以我们让RIP在处理完请求后直接把数据从公网返回给CIP,RIP和公网直连,不经过VIP,这样可以减小VIP的流量压力。这样请求从CIP到RIP再到CIP就构成了一个环形路径。
请求路径:
CIP -> VIP -> RIP -> 直接发给CIP,这个数据流是单向的,lvs会把RIP的mac地址套在ip数据包上发给RIP。
具体实现是把RIP的IP设置为VIP的IP,这样RIP发请求给CIP时,可以保证CIP收到的请求的源IP地址是VIP,和请求中的目标地址保持一致(都为VIP的IP)。VIP转发给RIP时,直接在IP包上套上一层RIP的MAC地址然后通过交换机发给RIP。
总结:该模式速度快,成本低。MAC地址欺骗,基于2层,用的最多,大多数据中心都用该模式,VIP和RIP必须在同一个网络中
隐藏VIP方法:对外隐藏,对内可见:(说白了就是把vip配在操作系统的虚拟网卡lo上)
kernel parameter:
目标mac地址为全F,交换机触发广播
/proc/sys/net/ipv4/conf/*lF/ proc目录在内核加载之后才有:https://www.cnblogs.com/DswCnblog/p/5780389.html
arp_ ignore.定义接收到ARP请求时的响应级别;
0:只要本地配置的有相应地址,就给予响应;
1:仅在请求的目标(MAC)地址配置请求
到达的接口上的时候,才给予响应;
arp_ announce:定义将自己地址向外通告时的通告级别;
0:将本地任何接口,上的任何地址向外通告;
1:试图仅向目标网络通告与其网络匹配的地址;
2:仅向与本地接口上地址匹配的网络进行通告;
**测试:**使用三个节点模拟负载均衡 (DR)
LVS:
node01:
ifconfig eth0:8 192.168.150.100/24
node02~node03:
1)修改内核:
echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
2)设置隐藏的vip:
ifconfig lo:3 192.168.150.100 netmask 255.255.255.255
RS中的服务:
node02~node03:
yum install httpd -y
service httpd start
vi /var/www/html/index.html
from 192.168.150.1x
LVS服务配置
node01:
yum install ipvsadm
ipvsadm -A -t 192.168.150.100:80 -s rr
ipvsadm -a -t 192.168.150.100:80 -r 192.168.150.12 -g -w 1
ipvsadm -a -t 192.168.150.100:80 -r 192.168.150.13 -g -w 1
ipvsadm -ln
验证:
浏览器访问 192.168.150.100 看到负载 疯狂F5
node01:
netstat -natp 结论看不到socket连接
node02~node03:
netstat -natp 结论看到很多的socket连接
node01:
ipvsadm -lnc 查看偷窥记录本
TCP 00:57 FIN_WAIT 192.168.150.1:51587 192.168.150.100:80 192.168.150.12:80
FIN_WAIT: 连接过,偷窥了所有的包
SYN_RECV: 基本上lvs都记录了,证明lvs没事,一定是后边网络层出问题
流程:
3.基于TUN隧道
建立VIP和RIP之间的一个隧道。隧道就是IP数据包“背着”另一个IP数据包的方式。类似VPN。
路径:
CIP->VIP , 然后把(CIP->VIP)的包封装一层,((CIP->VIP)DIP->RIP),由VIP的另一个网卡DIP发送给RIP,RIP收到后建立CIP和VIP间的映射,处理完毕后直接以VIP为原地址发送给CIP。
VIP和RIP可以不在一个局域网中
给rip的网卡配第二个ip地址:
ifconfig eth0:2 192.168.150.100/24
重设arpignore
echo 1 > arp_ignore
先改内核协议
echo 1 > / proc/ sys/net/ ipv4/ conf/eth0/arp_ ignore
echo 1 > / proc/ sys/net/ ipv4/ conf/all/arp_ ignore
echo 2 > /proc/ sys/net/ ipv4/ conf/eth0/arp_ announce
echo 2 > /proc/sys/net/ ipv4/ conf/all/arp_ announce
再配ip
给lvs的网卡配vip地址
ifconfig lo:2 192.168.150.100 netmask 255.255.255.255 #必须四个255,否则去150网络的请求不会走eth0会先走lo
LVS的调度算法
怎么确定具体转发给哪一台机器?
四种静态:
rr:轮循
wrr:
dh:
sh:
动态调度方法:
Ic:最少连接
wlc:加权最少连接
sed:最短期望延迟
nq: never queue
LBLC:基于本地的最少连接
DH:
LBLCR:基于本地的带复制功能的最少连接
linux内核对应的lvs功能的模块为ipvs
ipvs内核模块
yum install ipvsadm -y
管理集群服务
添加: -A -t|u|f service-address [-s scheduler]
-t: TCP协议的集群
-u: UDP协议的集群
service-address: IP:PORT
-f: FWM:防火墙标记
service-address: Mark Number
修改: -E
删除: -D -t|u|f service-address
ipvsadm -A -t 192.168.9.100:80 -S rr
管理集群服务中的RS
添加: -a -tlu|f service address -r server-address [-glilm] [-w weight] (在该规则下进行更详细的配置)
-t|u|f service-address:事先定义好的某集群服务
-r server-address:某RS的地址,在NAT模型中,可使用IP: PORT实现端口映射;
[-g|i|m]: LVS类型
-9: DR
-i: TUN
-m: NAT
[-W weight]:定义服务器权重
修改: -e
删除: -d -t|u|f service-address -r server-address
# ipvsadm -a -t 172.16.100.1:80 -r 192.168.10.8-g
# ipvsadm -a -t 172.16.100.1:80 -r 192.168.10.9 -9
查看
-L|l
-n:数字格式显示主机地址和端口
--stats:统计数据
--rate:速率
--timeout:显示tcp、tcpfin和udp的会话起时时长
-:C显示当前的ipvs连接状况
删除所有集群服务
-C: 清空ipvs规则
保存规则
-S
# ipvsadm -S > /path/to/somefile
载入此前的规则:
-R
# ipvsadm -R < /path/fom/somefile (从配置文件读入内存)
keepalive的lvs高可用搭建
高可用的问题:
1.如果lvs挂了,业务会下线,单点故障
2.如果RS挂了,一部分用户会请求异常,lvs还存有这个RS的负载记录
解决问题:
单点故障解决方式:1.主备(用的最多),主机配vip,备份机以最快的速度接管主机 2.主主,用动态dns等方式在前面再加一层。
讨论主备模式:
备机如何知道主机down掉了?模式一,备份机定期轮训主机,查看主机状态,down掉了就启动。模式二,主机定期向备机发送状态,如果过了几个周期备机都没有收到主机消息,认为主机挂掉启动备机。
keepalive:
企业追求自动化-!把人解耦出去~!用程序替代! -> keepalived !
代替人自动运维,解决单点故障,实现HA(高可用)
1,监控自己服务
2,Master通告自己还活着,Backup监听Master状态, Master挂 了,一堆Backup推举出一个新的Master
3,配置: vip,添加ipvs, keepalived是有配置文件
4,对后端server做健康检查
注:lvs和nginx都可以用keepalive
keepalive实践思路:
假设有四个节点,选出两个做为RIP主机,剩下两个作为主机和备机,先把主机和备机配置都清掉,然后配那两个RIP,
keepalived实验:
主机: node01~node04
node01:
ipvsadm -C
ifconfig eth0:8 down
----------------------------
node01,node04:
yum install keepalived ipvsadm -y
配置:
cd /etc/keepalived/
cp keepalived.conf keepalived.conf.bak
vi keepalived.conf
node01:
vrrp:虚拟路由冗余协议!
vrrp_instance VI_1 {
state MASTER // node04 BACKUP
interface eth0
virtual_router_id 51
priority 100 // node04 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.150.100/24 dev eth0 label eth0:3
}
}
virtual_server 192.168.150.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 192.168.150.12 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.150.13 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
scp ./keepalived.conf root@node04:`pwd`
查看帮助文件:
man 5 keepalive.conf
vi文本复制命令:http://c.biancheng.net/view/555.html
.,$-1y
主备和主从的关系:
主备是只有主机提供服务,主机挂掉才让备机上。主从是主机和从机都在提供服务,只不过从机为主机提供协同配合。
RIP挂掉了怎么办?怎么确定RIP挂掉了(例如百度)?
答案一:用ping(错误)
RIP工作在应用层,而ping工作在网络层,目的是确定网络连接是否畅通。ping连他之上的传输层tcp是否畅通都无法确定,更无法确定应用层。最简单的方式:访问他一下。
lo地址
eth是以太网卡,lo是本地环回地址,使用该接口可以用于系统内部发送和接受数据。网络接口是用来发送和接受数据包的单位,lo接口是虚拟网络接口,lo并不真实的向外界发送和接受数据,仅仅在系统内部发送和接受数据,所以虚拟网络接口不需要驱动程序。使用lo地址无法在etho接口上抓到包,只能在lo地址上抓到包。说白了,lo地址不走网卡,不走物理设备,仅仅走虚拟设备,本机之间的通信走网络层即可判定是本机,不需要向外转发,本机间程序监听lo网卡即可获取相应数据。
redis基本概念
单进程,单线程,单实例。使用epoll 技术。使用单进程,单线程的原因是,为了保证数据的一致性,顺序性指的是每个连接内的命令是有顺序的。默认拥有16个库。计算向数据移动。
注意,在做负载均衡的时候,或者网关路由的时候,尽量把相同的东西打到一个节点上去。
看进程
ps -fe | grep redis
启动redis,
redis-cli
redis-cli -h 看帮助
set k380:1 hello 一号库中存一个键值对
get k380:1
select 8 进入8号库
get k380:1 取值为空,因为redis的16个库之间是隔离的