集群基础知识及haproxy负载均衡
一:本文在单机web基础架构之上继续扩展知识与相关技能,实现集群的环境,集群首先要是要有多台web服务器,可以按组实现不同的功能,然后友负载集器进行策略性的调度,最终实现高并发、高可用的并具备数据异地灾备的web集群框架,具体如下:
1.1:为什么要使用集群:
单机性能无法满足业务需求(单机性能上限),并且单机出硬件问题或其他问题会导致网站无法访问(单机故障问题),切无法承受数十万上百万用户的并发访问:
1.2:单机无法实现的功能:
1.2.1:就近部署,服务器部署在距离用户最近的地方,或者每个主要城市有一个机房,是因为动态数据无法使用CDN进行有效的加速,因此将动态数据部署在距离用户越近的地方访问就越快。
1.2.2:异地灾备,重要数据相互备份到异地,可能是不同城市或者不通国家,未来可能是不同的星球或星系,
1.3:引入负载均衡器:
LVS Scheduling Method LVS 的调度方法:
1.3.1:静态调服方法
# RR—-轮询
# WRR—加权轮询
# DH—-目标地址hash
# SH—-源地址hash
1.3.2. 动态调服方法
# LC—-最少连接
# WLC—加权最少连接
# SED—-最少期望延迟
# NQ—-从不排队调度方法
# LBLC—基于本地的最少连接
# LBLCR–带复制的基于本地的最少连接
1.4:四层负载均衡和七层负载均衡
LVS官方文章:http://www.linuxvirtualserver.org/zh/
1.4.1:LVS Nat(地址转换)模式的工作方式:
#.客户端请求报文,源IP为客户端IP,源端口为客户端随机端口,目标IP为LVS的VSIP,目标端口为80或指定端口。
#.LVS服务器收到报文,根据调度算法计算出要讲请求分配给那台后端服务器
#.LVS使用DNAT技术分配报文,原地址为客户端IP,目标IP为后端web服务器IP, 后端服务器的端口可以更改
#.后端web服务器收到报文并进行响应,原地址为web服务器IP,目标IP为客户端IP
#.LVS 收到报文,将源IP改为服务器本身,目标IP还是客户端的,然后发送给客户端
注:nat模式的瓶颈是带宽,因为进入的流量和外出的流量都要经过LVS服务器的虚IP地址
1.4.2:DR(直接路由)模式: 属于二层的负载技术,不能夸vlan,MAC 地址是通过arp协议广播,但是vlan是隔离arp广播的,而DR陌生是通过修改MAC 地址实现的,不修改源IP和目标IP。
#客户端发送报文,源IP为本机IP,源端口随机,目标IP为LVS的VSIP,目标端口为请求的端口。
#LVS 收到报文,将源目标MAC 改为web服务器的manc地址,VIP不变,然后将报文发送给web服务器。
#web服务器收到报文,此时的源IP为客户端,源端口为客户端的随机端口,目标IP为VSIP,目标端口客户端请求的端口,目标MAC地址为web服务器自己的mac地址,然后web服务器处理报文请求,将目标IP 改为客户端,源IP是VSIP,然后发送给自己的网关交与客户端。
1.4.3:IP 隧道模式TUN,与DR类似,但是不受IP的限制,RIP/DIP/VIP都得是公网IP,LVS服务器的VIP也必须是公网IP,其不修改MAC与IP,只是将报文封装在一个报文里面在发送给web服务器进行处理,web服务器收到后将报文解封装,发现请求的ISIP是本机,就进行构建请求然后根据源IP进行回复。
#客户端发送请求报文,源IP为客户端IP,源端口为客户端随机端口,目标IP为LVS的VSIP,目标端口为80或指定端口。
#LVS收到报文根据算法将报文封装在报文里面发送给后算web服务器
#web服务器将报文解封装,发现请求的VIP是自己
#web服务器构建请求并安装源IP回复报文
1.5:七层负载均衡:
与客户端建立三次握手和四次断开,接收到用户请求后与后端web服务器再建立连接、请求资源、接收资源并返回给用户。
nignx默认支持的调度算法:
round-robin:轮训调度,默认
ip_hash:会话绑定
least_conn:最少会话链接
1.6:四层和七层的区别:
客户端在建立三次握手的时候和后端web服务器建立连接,负载均衡只是转发客户端的请求到后端web服务器,并且在有些情况下要修改报文的目标地址,比如LVS nat模式,四层是转发,七层负载均衡的算法比四层多一些,比如URL、cookie、UA(客户端浏览器类型)等七层支持的协议来做负载均衡,客户端与七层负载均衡直接建立三次握手和四次断开,七层负载将后端服务器和客户端完全隔离,收到客户端的请求后七层代理连接web服务器进行web请求,然后we服务器将结果发送给七层代理,七层代理服务器在把结果发送给客户端,所以相比较的话七层没有四层性能好,但是四层没有七层功能多也没有七层比较灵活,因此可以使用四层+七层的方式,即四层负载转发,七层负载高级功能的实现,比如动静分离、URL重写等功能,
总结:
四层是转发:对内存和CPU的消耗比较小,是属于内核级别的转发,配置相对比较简单,由于是工作在四层,因此凡是tcp协议端口的服务都可以实现负载,比如web服务器、mysql等。
七层是代理:基于应用层代理,可以对访问的http协议进行自定义的处理,使用正则表达式实现URL 重写、过滤、动静分离、图片转发等功能。
阿里云的SLB技术实现,链接地址:https://yq.aliyun.com/articles/1803
tengine官方网站,链接地址:http://tengine.taobao.org/download_cn.html
1.7:关于机房灾备:
中小企业机房建设灾备基础:http://www.yunweipai.com/archives/9242.html
某厂商的多机房文档:http://blog.csdn.net/blade2001/article/details/50069547
参见国家标准文档:国家标准GBT20988-2007《信息系统灾难恢复规范》
二:反向代理是Haproxy:
对比nginx,nginx 不支持自定义URL 检测,nginx 的session 保持只能基于ip_hash,而haproxy支持cookie等方式,nginx 的默认算法较少,不如haproxy多,另外haproxy是专门做代理的,因此在代理性能上优于nginx,而nginx 的web性能是比较好的,因此nginx 可以作为web服务器并作为访问量不是特别的web服务器做代理。
2.1:下载haproxy:
官网下载地址:http://www.haproxy.org/
系统版本:Centos 7.2-1511
haproxy版本:当前最新版本1.7.1
2.2:部署haproxy:
2.2.1:安装部署haproxy,并配置haproxy通过四层进行反向负载:
# tar xvf haproxy-1.7.1.tar.gz
# yum install pcre pcre-devel openssl openssl-devel
# make TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 PREFIX=/usr/local/haproxy #开启SSL和zlip的支持
# make install PREFIX=/usr/local/haproxy
# cp examples/haproxy.init /etc/init.d/haproxy
# chmod a+x /etc/init.d/haproxy
# ln -sv /usr/local/haproxy/sbin/haproxy /usr/sbin/haproxy
# mkdir /etc/haproxy
[root@localhost haproxy-1.7.1]# cat /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /usr/local/haproxy
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local0 info
defaults
option http-keep-alive
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
mode tcp
log global
server web1 192.168.10.128:8080 check inter 5000 fall 1 rise 2
[root@localhost haproxy-1.7.1]# /etc/init.d/haproxy restart
Restarting haproxy (via systemctl): [ OK ]
2.2.2:访问web 管理界面:
2.2.3:开启访问日志:
# vim /etc/rsyslog.conf
14 # Provides UDP syslog reception
15 $ModLoad imudp #去掉原来的注释,
16 $UDPServerRun 514 #日志基于UDP的514端口
92 local0.* /var/log/haproxy.log
# systemctl restart rsyslo
2.2.4:刷新web管理界面,并验证是否有日志产生:
2.3:部署两台web服务器,并通过四层的负载方式访问web服务器:
#在另外两台台服务器安装apache服务,并各部署一个简单的web界面实现通过代理访问,
2.3.1:web服务器各配置如下:
[root@node9 ~]# grep ^Listen /etc/httpd/conf/httpd.conf
Listen 80
[root@node9 ~]# cat /var/www/html/index.html
web1
[root@node9 ~]# grep ^Listen /etc/httpd/conf/httpd.conf
Listen 8080
[root@node10 ~]# cat /var/www/html/index.html
web2
2.3.2:haproxy配置如下:
[root@localhost haproxy-1.7.1]# vim /etc/haproxy/haproxy.cfg
global #global是haproxy进程相关的配置项
maxconn 100000
chroot /usr/local/haproxy
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local0 info
defaults #设置默认参数,如果后面的配置有相同的配置项则使用后面的
maxconn 100000
mode tcp
option tcplog
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global #记录日志,可以不在haproxy 记录日志,因为访问量较大的时候会影响性能
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
mode tcp #使用tcp模式进行负载,即四层负载,对应的还有http即七层负载
log global
server web1 192.168.10.129:8080 check inter 3000 fall 15 rise 10 #两台不同端口的后端web服务器
server web2 192.168.10.130:80 check inter 3000 fall 15 rise 10
#inter是监控检查时间间隔,即每间隔3秒进行一次检查,rise是连续检查10次失败后将服务器从负载删除,fall是连续15次监控检查成功后重新添加至负载,一般fall大于rise几次,为避免网络或服务不稳定
[root@localhost haproxy-1.7.1]# /etc/init.d/haproxy restart #最后重启haproxy服务
Restarting haproxy (via systemctl): [ OK ]
2.3.3::访问web界面验证:
2.3.4:验证haproxy 控制界面是否检查到后端web 服务器:
2.4:配置使用七层进行负载:
2.4.1:haproxy配置如下:
[root@localhost ~]# cat /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /usr/local/haproxy
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local0 info
defaults
maxconn 100000
mode tcp
option tcplog
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
mode http #将模式改为http
log global
server web1 192.168.10.129:8080 check inter 3000 fall 15 rise 10
server web2 192.168.10.130:80 check inter 3000 fall 15 rise 10
2.4.2:验证web访问:
2.5:传递客户端真实IP:
2.5.1:haproxy配置:
[root@localhost ~]# cat /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /usr/local/haproxy
uid 99
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local0 info
defaults
maxconn 100000
mode tcp
option tcplog
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 0.0.0.0:80
option forwardfor header X-Forwarded-xxx #自定义传递IP参数,后端web服务器写X-Forwarded-xxx,如果写option forwardfor则后端服务器web格式为X-Forwarded-For log global
server web1 192.168.10.129:8080 check inter 3000 fall 15 rise 10
server web2 192.168.10.130:80 check inter 3000 fall 15 rise 10
2.5.2:web服务器 日志格式:
#apache 配置:
LogFormat "%{X-Forwarded-xxx}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
#tomcat 配置:
pattern='%{X-Forwarded-xxx}i %l %T %t "%r" %s %b "%{User-Agent}i"'/>
#nginx 日志格式:
log_format main '"$http_x_forwarded_xxx" - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
2.5.3:验证web服务器收到客户端真实IP:
Nginx的访问日志:
Apache的访问日志: