HA Proxy
kv key-value
取模法
一致性哈希算法:consistent hashing
偏斜:虚拟节点
LB:按工作方法分类
基于tcp调度:
lvs,haproxy(模拟实现,未突破套接字限制),nginx
基于application layer调度:
http:haproxy,nginx,ats,apache
mysql:mysl-proxy
web arch:haproxy
mode:http,tcp在用户空间模拟tcp服务进行调度(https,mysql)
HAProxy:不提供任何HA功能,只提供代理proxy
代理:(http)掮客(broker)
正向代理:
反向代理:
代理的作用:web缓存(加速)、反向代理、内容路由(根据流量及内容类型等,将请求转发至特定服务器)、转码器(前段压缩)
在代理服务器上添加via首部
缓存作用:
减少冗余内容的传输:
节省带宽、缓解网络瓶颈
降低对原始服务器的请求压力
降低传输延迟
HAProxy:只是http协议的反向代理,不提供反向代理,但额外支持对基于tcp通信的应用做LB
HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。
Big O: 评判数据结构复杂度
O(1):
O(logN): 红黑树
O(n)
O(n^2)
O(2^n)
haproxy: 弹性二叉树
数据结构:
Remote Desktop Protocol
Windows: 3389
1.4版本——提供较好的弹性:衍生于1.2版本,并提供了额外的新特性,其中大多数是期待已久的。
客户端侧的长连接(client-side keep-alive)
TCP加速(TCP speedups)
响应池(response buffering)
RDP协议
基于源的粘性(source-based stickiness)
更好的统计数据接口(a much better stats interfaces)
更详细的健康状态检测机制(more verbose health checks)
基于流量的健康评估机制(traffic-based health)
支持HTTP认证
服务器管理命令行接口(server management from the CLI)
基于ACL的持久性(ACL-based persistence)
日志分析器
1.3版本——内容交换和超强负载:衍生于1.2版本,并提供了额外的新特性。
内容交换(content switching):基于任何请求标准挑选服务器池;
ACL:编写内容交换规则;
负载均衡算法(load-balancing algorithms):更多的算法支持;
内容探测(content inspection):阻止非授权协议;
透明代理(transparent proxy):在Linux系统上允许使用客户端IP直接连入服务器;
内核TCP拼接(kernel TCP splicing):无copy方式在客户端和服务端之间转发数据以实现数G级别的数据速率;
分层设计(layered design):分别实现套接字、TCP、HTTP处理以提供更好的健壮性、更快的处理机制及便捷的演进能力;
快速、公平调度器(fast and fair scheduler):为某些任务指定优先级可实现理好的QoS;
会话速率限制(session rate limiting):适用于托管环境;
性能:
HAProxy借助于OS上几种常见的技术来实现性能的最大化。
单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。
O(1)事件检查器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测。
在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽;
借助于Linux 2.6 (>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting);
内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长;
树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;
优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;
精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;
所有的这些细微之处的优化实现了在中等规模负载之上依然有着相当低的CPU负载,甚至于在非常高的负载场景中,5%的用户空间占用率和95%的系统空间占用率也是非常普遍的现象,这意味着HAProxy进程消耗比系统空间消耗低20倍以上。因此,对OS进行性能调优是非常重要的。即使用户空间的占用率提高一倍,其CPU占用率也仅为10%,这也解释了为何7层处理对性能影响有限这一现象。由此,在高端系统上HAProxy的7层性能可轻易超过硬件负载均衡设备。
在生产环境中,在7层处理上使用HAProxy作为昂贵的高端硬件负载均衡设备故障故障时的紧急解决方案也时长可见。硬件负载均衡设备在“报文”级别处理请求,这在支持跨报文请求(request across multiple packets)有着较高的难度,并且它们不缓冲任何数据,因此有着较长的响应时间。对应地,软件负载均衡设备使用TCP缓冲,可建立极长的请求,且有着较大的响应时间。
可以从三个因素来评估负载均衡器的性能:
会话率
会话并发能力
数据率
nginx:
server { 每个server相当一个前端
}
server {
location ~* \.php$ 定义条件
proxy_pass 代理
location / {
}
}
proxy_pass:
upstream { 代理的后端服务器列表
leastconn 最少连接算法
server 后端服务器
server
}
upstream {
}
haproxy:
frontend 前端(监听的端口等)
use_backend 与后端建立关联(条件式请求)
default_backend 默认后端
backend
balancer 指明调度方法
server
server
若前后端不分离,通常用于定义单个后端的情况
listen: 监听
server
default 为以上三项提供默认参数
配置文件:/etc/haproxy/haproxy.cfg
全局配置:
代理配置
现有三台机器(CentOS7)分别为www(IP192.168.2.16),web1(IP192.168.2.18),localhost(IP192.168.2.60)
首先在www主机上安装haproxy
[root@www ~]# yum install haproxy -y
[root@www ~]# rpm -ql haproxy #查看生成的文件
在web1和localhost上分别安装httpd并提供主页文件
[root@web1 ~]# yum install httpd
[root@web1 ~]# echo "web1
" > /var/www/html/index.html
[root@localhost ~]# echo "web2
" > /var/www/html/index.html
[root@web1 ~]# systemctl start httpd.service
[root@web1 ~]# ss -tnlp
配置haproxy:
[root@www ~]# cd /etc/haproxy/
[root@www haproxy]# vim haproxy.cfg
目前下面的配置文件没用,删除上图以下的配置文件
[root@www haproxy]# systemctl start haproxy.service
[root@www haproxy]# systemctl status haproxy.service -l #查看运行状态
尝试访问,效果为轮询,因balance为roundrobin
看是否能实现健康状态检查:
[root@web1 ~]# systemctl stop httpd.service
<<<<<<<<<<<<<<<<<部分解释>>>>>>>>>>>>>>
global:
log 127.0.0.1 local2 记录日志,通过日志server
chroot /var/lib/haproxy 将根目录切换至此目录安全运行
pidfile /var/run/haproxy.pid PID文件位置
maxconn 4000 最大连接数
user haproxy 运行进程的用户
group haproxy
daemon 启动为守护进程
# turn on stats unix socket
stats socket /var/lib/haproxy/stats 本地访问统计数据时可以基于共享内存方式
nbproc 启动haproxy的进程个数,只能用于守护进程时
ulimit-n 设定每个进程打开的的最大文件数量,默认自行计算
spread-checks
<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>
常需要调整的值:log,nbproc,maxconn,spread-checks
下面来配置一下日志:
[root@www haproxy]# systemctl restart rsyslog.service #重启日志服务
[root@www ~]# systemctl status rsyslog.service
[root@www ~]# ss -unlp #查看514端口是否监听
[root@web1 ~]# systemctl start httpd.service 启动web1上的httpd
再次尝试访问查看是否可轮询
查看后端服务器的日志:(实际生产中应记录实际访问的客户端IP才有意义)
总结:
HAProxy:
http协议反向代理
tcp层的LB
特性:event-driven(事件驱动),ebtree(弹性二叉树)
配置:/etc/haproxy/haproxy.cfg(主配置文件)
/usr/sbin/haproxy(主程序)
启动方式:
CentOS 6: /etc/rc.d/init.d/haproxy (调用脚本)
CentOS 7: haproxy.service (unit file)
配置分为两段:
global:
log
maxconn 最大并发连接
...
proxies (代理相关)
defaults,frontednd,bakcend,listen
HAProxy(2)
代理参数:
balance:指明负载均衡的调度算法
动态:权重可动态调整(服务器自行调整)
静态:调整权重不会实时生效
roundrobin:加权轮询,动态算法,每个后端主机最多支持4128个连接
static-rr:轮询,静态算法,每个后端主机支持的数量无上限
leastconn:根据后端主机的负载数量(最少连接)进行调度,仅适用于长连接的会话,动态,不适于http
source:源地址hash,基于后端服务器的权重总数,不过当后端服务器数量或权重变化时,后果...
hash-type:hash类型
map-based:取模法,静态
consistent:一致性哈希法,动态
uri:
hash-type:
map-based:取模法,静态
consistent:一致性哈希法,动态
url_param:根据url中的param参数的值进行调度,把值进行hash计算,并除以总权重:(比如基于username)
hash-type:
map-based:取模法,静态
consistent:一致性哈希法,动态
hdr(
[root@www haproxy]# vim haproxy.cfg
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
[root@www ~]# systemctl status haproxy.service
[root@web1 ~]# for i in {1..10}; do echo "Page $i Web1
" > /var/www/html/text$i.html; done
[root@web1 ~]# ls /var/www/html/
[root@localhost ~]# for i in {1..10}; do echo "Page $i Web2
" > /var/www/html/text$i.html; done
此时更换不同客户端进行测试,对同一个uri的请求一定会调度到同一httpd服务器响应,此时若其中一个服务器宕机,则根据规定的算法向后轮询且剩下的服务访问依然遵循uri调度,因本次环境不具备不演示
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
bind:
只能用于frontend,listen
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl restart haproxy.service
[root@www ~]# systemctl status haproxy.service
mode:
HAProxy的工作模式,默认为TCP,只有在服务端和客户端都为http协议时才可使用http
tcp, http, health
log:
maxcoon:最大连接数
default_backend:
为frontend指明使用的默认后端
use_backend:条件式后端调用
K.I.S.S:Keep it simple,stupid
server:
server
settings:
backup: 设定当前server为backup server;
check: 健康状态检测;
inter
fall: up --> down, soft state, soft state, hard state;
rise:down --> up,
cookie
maxconn: 此服务器接受的并发连接的最大数量;
maxqueue: 请求队列的最大长度;
observe: 根据流量判断后端server的健康状态;
weight: 指定权重,默认为1,最大为256;0表示不被调度;
redir
后端为http服务器做健康状态检测时的检测方法:
option httpchk
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
基于浏览器cookie实现session sticky:
backend websrvs
balance roundrobin
cookie SERVERID insert nocache indirect
server web1 172.16.100.68:80 check weight 1 cookie websrv1
server web2 172.16.100.69:80 check weight 3 cookie websrv2
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
要点:
(1) 每个server有自己惟一的cookie标识;
(2) 在backend中定义为用户请求调度完成后操纵其cookie
启用stats:
listen statistics
bind *:9090
stats enable
stats hide-version
#stats scope .
stats uri /haproxyadmin?stats
stats realm "HAPorxy\ Statistics"
stats auth admin:mageedu
stats admin if TRUE
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl restart haproxy.service
[root@www ~]# systemctl status haproxy.service
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
显示的内容好像比刚才少了,这是因为我们没有赋予当前账户管理权限:
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
向日志中记录额外信息:
capture request header
capture response header
当mode为http时,记录详细的日志信息(默认已启用)
启用或禁用提前将HTTP请求记入日志
[no] option logasap
[root@localhost ~]# vim /etc/httpd/conf/httpd.conf
[root@localhost ~]# systemctl reload httpd.service
错误页面重定向
errorfile:使用haproxy主机本地文件进行响应
errorloc,errorloc302:使用指定的url进行响应,响应状态码为302,不适用与GET以外的其他方法
访问控制:
http_request
tcp_request
添加请求或响应报文首部:
reqadd
rspadd
[root@www haproxy]# vim haproxy.cfg
[root@www ~]# systemctl reload haproxy.service
option: http-server-close 长连接server端断开
option http-pretend-keepalive 假装haproxy向server请求为保持连接
ACL:
定义及调用
补充:动静分离的示例:
frontend main
bind *:80
bind *:8080
acl url_static path_beg -i /static /p_w_picpaths /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend appsrvs
#---------------------------------------------------------------------
# static backend for serving up p_w_picpaths, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static1 172.16.100.11 check
server static2 172.16.100.12 check
backend appsrvs
balance roundrobin
option forwardfor except 127.0.0.1 header X-Client
option httpchk
cookie SERVERID insert indirect nocache
server web1 172.16.100.7:80 check cookie web1
server web2 172.16.100.8:80 check cookie web2