当然从成本上,硬负载绝对是土豪公司的工具,便宜的十来万RMB,贵则上百万RMB。而软负载只需要一台Linux服务器的钱就足够了。此外LVS的部署复杂度相比于Nginx会高那么一点,但是Nginx的七层负载的灵活性是四层负载的无法比拟的。
在实际工作中大家更多会接触到上图的架构模型,从功能职责上又可以划分地域级、集群级和应用级的负载:
地域级的负载均衡使用的是DNS的智能解析来完成的,DNS全称DomainNameSystem,中文叫域名系统(服务)协议,一般都会采用云服务厂商的DNS系统,我们知道域名是需要花钱购买的,而厂商会附带一个免费的域名解析套餐,如果需要对域名进行域名智能解析,就需要付费给厂商获取相应的服务。
Nginx作为应用级负载也有自己的并发处理上限,如果超过上限了那么只能通过再上一层加一个更高处理性能的负载均衡器作为解决,而LVS可以很好担任集群级的负载重任。如果是土豪公司可以在自己选择使用硬负载来代替LVS,硬负载虽然贵也有自己的优势,例如防火墙、加密、高性能处理等。
Nginx
Nginx是一个高性能的反向代理服务器,也是稳定且高效的基于七层的负载均衡器。Nginx可以根据以随机、加权轮询,IP哈希、URL哈希等方式调度后端真是服务器,Nginx也支持对后端服务器的健康检查功能。
LVS
LVS即LinuxVirtualServer,翻译中文为Linux虚拟服务器,目前LVS是已经被集成到Linux内核模块中,LVS的工作模式分为NAT模式、TUN模式以及DR模式。那么在实战中,更多会Keepalived+LVS一起集成使用,Keepalived可以自动将LVS备用调度器升级为主调度器,最终实现整个集群系统的高负载、高可用。
本篇的重点主要讲解Keepalive+LVS+Nginx+.NetCore的搭建与使用。
效果图
PS:上图是我完成搭建后录制的视频转gif,因为中间有等待的一分钟,为了观看效果剪断了。
Web1与Web2是同一个Nginx,Web3和Web4是同为另外的一个Nginx。在图里可见需要过一段时间才能从一个Nginx切换到另外一个Nginx,原因主要是LVS会根据访问客户端的IP+端口在会话时间内重复的转发到同一个目标服务器。而控制这个会话时间的可以通过设置ipvsadm--persistent与--set这两个参数决定。
LVS的三种工作模式
NAT(NetworkAddressTranslation)-网络地址转换模式。
首先,外部请求会经过LVS的VIP(VirtualIPAddress);接着,LVS会根据预设的调度算法选择一台真实的服务器进行数据请求包转发,转发前会把原数据包的目标地址与目标端口修改为真实服务器的地址与端口;最后,LVS在得到响应数据包后会把源地址与源端口改为VIP及调度器相应的端口。因为由于所有的请求与响应都会经过LVS调度器转发,因此容易成为集群的瓶颈。
TUN-隧道模式
因为NAT会的瓶颈问题,因此TUN模式采用用了请求与响应数据分离的思路,让调度器仅处理数据请求,让真实服务器响应数据包直接返回给客户端,需要注意的是该模式下的真实服务器需要与外部网络连接。另外TUN模式下需要在LVS调度器与真实服务器之间创建隧道连接,同样会增加服务器的负担。
DR(DirectRouting)-直接路由模式
DR模式也是采用请求与响应分离的思路,由真实服务器直接响应客户端,但是它的报文转发方法有所不同,在不修改数据报文的情况下,将数据帧的MAC地址修改为需要转发到的真实服务器MAC地址,免去了TUN中的IP隧道开销。这种方式是三种负载调度机制中性能最高最好的,但是LVS调度器与真实后端服务器必须在一个局域网内。
LVS的部署
接下来的部署操作将实现上图Keepalived+LVS+Nginx的多层负载均衡,LVS将是以DR模式实现。
两台LVS服务器(主从)
基础依赖安装
yuminstallgcc yum-yinstallopenssl-devel yum-yinstalllibnllibnl-devel yuminstall-ylibnfnetlink-devel yum-yinstallnet-tools yuminstallvim-y |
yuminstall-ykeepalivedipvsadm |
vim/etc/keepalived/keepalived.conf |
global_defs {
router_id LVS_MASTER # 设置lvs的id,在一个网络内应该是唯一的
}
vrrp_instance VI_1 {
state MASTER #指定Keepalived的角色,MASTER为主,BACKUP为备 记得大写
interface ens33 #网卡id 不同的电脑网卡id会有区别 可以使用:ip a查看
virtual_router_id 51 #虚拟路由编号,主备要一致
priority 100 #定义优先级,数字越大,优先级越高,主DR必须大于备用DR
advert_int 1 #检查间隔,默认为1s
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress {
192.168.174.128/24 #定义虚拟IP(VIP)为192.168.174.128,可多设,每行一个
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.174.128 80 {
delay_loop 6 # 设置健康检查时间,单位是秒
lb_algo rr # 设置负载调度的算法为wlc
lb_kind DR # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 192.168.88.137 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.88.139 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
} |
vim/etc/keepalived/keepalived.conf |
global_defs {
router_id LVS_SLAVE # 设置lvs的id,在一个网络内应该是唯一的
}
vrrp_instance VI_1 {
state BACKUP #指定Keepalived的角色,MASTER为主,BACKUP为备 记得大写
interface ens33 #网卡id 不同的电脑网卡id会有区别 可以使用:ip a查看
virtual_router_id 51 #虚拟路由编号,主备要一致
priority 50 #定义优先级,数字越大,优先级越高,主DR必须大于备用DR
advert_int 1 #检查间隔,默认为1s
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress {
192.168.174.128/24 #定义虚拟IP(VIP)为192.168.174.128,可多设,每行一个
}
}
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.174.128 80 {
delay_loop 6 # 设置健康检查时间,单位是秒
lb_algo rr # 设置负载调度的算法为wlc
lb_kind DR # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 192.168.88.137 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.88.139 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
} |
vim/etc/sysconfig/network-scripts/ifcfg-lo:0 |
DEVICE=lo:0 IPADDR=192.168.88.128 NETMASK=255.255.255.255 BROADCAST=192.168.88.128 ONBOOT=yes NAME=lvs_vip |
vim/etc/sysctl.conf |
net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.all.arp_announce=2 net.ipv4.conf.lo.arp_ignore=1 net.ipv4.conf.lo.arp_announce=2 |
sysctl-p systemctlrestartnetwork |
Nginx的部署
在两台Nginx服务器都执行以下指令
添加源并安装
rpm-Uvhhttp://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm yuminstall-ynginx |
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
#开始
upstream 192.168.88.139{
server localhost:5001 weight=1;
server localhost:5002 weight=1;
}
server {
listen 80;
server_name 192.168.88.139;
charset utf8;
client_max_body_size 50m;
client_body_buffer_size 256k;
location / {
proxy_pass http://192.168.88.139;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
#结束
} |
systemctlstartnginx.service systemctlenablenginx.service |
firewall-cmd--permanent--zone=public--add-port=80/tcp firewall-cmd--reload |
ipvsadm-Ln |
ipvsadm-Lnc |
rpm-Uvhhttps://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm |
sudoyuminstallaspnetcore-runtime-2.2 |
nohupdotnetTest1.dll--server.urls"http://*:5001"& nohupdotnetTest1.dll--server.urls"http://*:5002"& |
yuminstall-yvsftpd |
vim/etc/vsftpd/vsftpd.conf |
anonymous_enable=NO listen=YES #listen_ipv6=YES |
systemctlstartvsftpd systemctlenablevsftpd |
firewall-cmd--permanent--zone=public--add-service=ftp firewall-cmd--reload |
vim/etc/vsftpd/user_list vim/etc/vsftpd/ftpusers #root |
setenforce0 vim/etc/selinux/config #将SELINUX=enforcing改为SELINUX=permissive |