1、Haproxy简介javascript
HAproxy 是一款高性能的TCP和HTTP负载均衡器。其功能是用来提供基于cookie的持久性,基于内容的交换,过载保护的高级流量管制,自动故障切换,以正则表达式为基础的标题控制运行时间,基于Web的报表,高级日志记录以帮助排除故障的应用或网络,以及其余一些功能。HAProxy运行在当前的硬件上,事件驱动的状态机达到每秒20000点击和超过亿单元以太网,甚至支持数以万计的同步链接。php
HAProxy是法国人Willy Tarreau我的开发的一个开源软件,目标是应对客户端10000以上的同时链接,为后端应用服务器、数据库服务器提供高性能的负载均衡服务。在底层数据结构方面,旧版本HAProxy曾经使用过红黑树,用于任务调度、负载均衡等方面。可是Willy Tarreau认为,在事件响应很是频繁的状况下,任务插入、删除的频率很是高,这时候使用红黑树存在性能瓶颈,尤为不能接受红黑树删除节点的时间复杂度为O(log n)。所以,他发明了一种新的数据结构,叫作弹性二叉树(elastic binary tree),简称ebtree。css
目前新版本的HAProxy已使用ebtree,而除了HAProxy以外,尚未其它著名的开源软件使用ebtree。能够这么说,HAProxy最有特点的地方就是ebtree,ebtree名符实际上是HAProxy的独门武器。html
2、Haproxy的特性前端
HAProxy是免费、极速且可靠的用于为TCP和基于HTTP应用程序提供高可用、负载均衡和代理服务的解决方案,尤为适用于高负载且须要持久链接或7层处理机制的web站点。java
客户端侧的长链接(client-side keep-alive)web
TCP加速(TCP speedups)正则表达式
响应池(response buffering)算法
基于源的粘性(source-based stickiness)数据库
更好的统计数据接口(a much better stats interfaces)
更详细的健康状态检测机制(more verbose health checks)
基于流量的健康评估机制(traffic-based health)
基于ACL的持久性(ACL-based persistence)
ACL:编写内容交换规则;
负载均衡算法(load-balancing algorithms):更多的算法支持;
分层设计(layered design):分别实现套接字、TCP、HTTP处理以提供更好的健壮性、更快的处理机制及便捷的演进能力;
快速、公平调度器(fast and fair scheduler):为某些任务指定优先级可实现理好的QoS;
会话速率限制(session rate limiting):适用于托管环境;
3、Haproxy的性能
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);
MRU内存分配器在固定大小的内存池中可实现即时内存分配,这可以显著减小建立一个会话的时长;
树型存储:侧重于使用做者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少链接队列;
优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程当中重读任何内存区域;
精心地下降了昂贵的系统调用,大部分工做都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;
全部的这些细微之处的优化实现了在中等规模负载之上依然有着至关低的CPU负载,甚至于在很是高的负载场景中,5%的用户空间占用率和95%的系统空间占用率也是很是广泛的现象,这意味着HAProxy进程消耗比系统空间消耗低20倍以上。所以,对OS进行性能调优是很是重要的。即便用户空间的占用率提升一倍,其CPU占用率也仅为10%,这也解释了为什么7层处理对性能影响有限这一现象。由此,在高端系统上HAProxy的7层性能可轻易超过硬件负载均衡设备。
在生产环境中,在7层处理上使用HAProxy做为昂贵的高端硬件负载均衡设备故障故障时的紧急解决方案也时长可见。硬件负载均衡设备在“报文”级别处理请求,这在支持跨报文请求(request across multiple packets)有着较高的难度,而且它们不缓冲任何数据,所以有着较长的响应时间。对应地,软件负载均衡设备使用TCP缓冲,可创建极长的请求,且有着较大的响应时间
4、Haproxy基本实现
haproxy的安装,这里演示的为centos 7,经过yum光盘镜像安装
[root@localhost ~]# yum install haproxy [root@localhost ~]# rpm -ql haproxy /etc/haproxy/haproxy.cfg #主配置文件 /etc/logrotate.d/haproxy #日志回滚 /usr/lib/systemd/system/haproxy.service #服务管理单元 /usr/sbin/haproxy #haproxy主程序
这里先实现一个最基本的基于轮询负载负载均衡,先简单简单配置两个httpd服务器
[root@wlw1 ~]# echo 'My web1 192.168.0.45' > /var/www/html/index.html [root@wlw2 ~]# echo 'My web2 192.168.0.66' > /var/www/html/index.html
haproxy服务器配置以下,
vim /etc/haproxy/haproxy.cfg frontend main *:80 default_backend webserver backend webserver balance roundrobin server web.ip45 192.168.0.45:80 check server web.ip66 192.168.0.66:80 check
实验结果,能够看到实现了轮询效果
[root@localhost ~]# curl http://192.168.0.56 My web1 192.168.0.45 [root@localhost ~]# curl http://192.168.0.56 My web2 192.168.0.66 [root@localhost ~]# curl http://192.168.0.56 My web1 192.168.0.45 [root@localhost ~]# curl http://192.168.0.56 My web2 192.168.0.66
5、Haproxy常见全局global配置选项及其用法
①、log:经过logserver记录日志,定义全局的syslog服务器,最多能够定义两个
vim /etc/haproxy/haproxy.cfg global log 127.0.0.1 local2 [root@localhost ~]# vim /etc/rsyslog.conf $ModLoad imudp #开启syslog监听服务 $UDPServerRun 514 local2.* /var/log/haproxy.log
配置好全局日志后经过查看访问日志查询是否成功生效
[root@localhost ~]# tail /var/log/haproxy.log Oct 24 06:25:51 localhost haproxy[1626]: 192.168.0.56:39072 [24/Oct/2015:06:25:51.817] main webserver/web.ip45 4/0/4/8/16 200 289 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1" Oct 24 06:25:52 localhost haproxy[1626]: 192.168.0.56:39075 [24/Oct/2015:06:25:52.687] main webserver/web.ip66 0/0/1/8/9 200 289 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1" #上面信息,192.168.0.56发送的请求,由main前端响应,这里对应咱们配置文件中frontend配置的名字,发送给webserver/web.ip45后端服务器的web.ip45web服务器处理。
②、log-send-hostname <string>:在syslog信息的首部添加当前主机名,能够为“string”指定的名称,也能够缺省使用当前主机名;
③、nbproc <number>:指定启动的haproxy进程的个数,只能用于守护进程模式的haproxy;默认只启动一个进程,鉴于调试困难等多方面的缘由,通常只在单进程仅能打开少数文件描述符的场景中才使用多进程模式;
④、ulimit-n <number>:设定每进程所可以打开的最大文件描述符数目,默认状况下其会自动进行计算,所以不推荐修改此选项;
⑤、maxconn <number>:设定每一个haproxy进程所接受的最大并发链接数,“ulimit -n”自动计算的结果正是参照此参数设定的;
⑥、spread-checks <0..50, in percent>:在haproxy后端有着众多服务器的场景中,在精确的时间间隔后统一对众服务器进行健康情况检查可能会带来意外问题;此选项用于将其检查的时间间隔长度上增长或减少必定的随机时长;
6、Haproxy常见代理配置选项及其用法
①、balance:定义负载均衡算法,可用于“defaults”、“listen”和“backend”。
支持如下算法(动态:权重可动态调整,修改权重后无需重启服务。静态:调整权重不会实时生效,须要重启服务)
roundrobin: 基于权重轮询,动态算法,每一个后端主机最多支持4128个链接;
static-rr:基于权重轮询,静态算法,每一个后端主机支持的数量无上限;
leastconn:新的链接请求被派发至具备最少链接数目的后端服务器;在有着较长时间会话的场景中推荐使用此算法,如LDAP、SQL等,其并不太适用于较短会话的应用层协议,如HTTP;此算法是动态的,能够在运行时调整其权重;
source:将请求的源地址进行hash运算,并由后端服务器的权重总数相除后派发至某匹配的服务器;这可使得同一个客户端IP的请求始终被派发至某特定的服务器;不过,当服务器权重总数发生变化时,如某服务器宕机或添加了新的服务器,许多客户端的请求可能会被派发至与此前请求不一样的服务器;经常使用于负载均衡无cookie功能的基于TCP的协议;其默认为静态,不过也可使用hash-type修改此特性;
uri:对URI的左半部分(“问题”标记以前的部分)或整个URI进行hash运算,并由服务器的总权重相除后派发至某匹配的服务器;这可使得对同一个URI的请求老是被派发至某特定的服务器,除非服务器的权重总数发生了变化;此算法经常使用于代理缓存或反病毒代理以提升缓存的命中率;须要注意的是,此算法仅应用于HTTP后端服务器场景;其默认为静态算法,不过也可使用hash-type修改此特性;
URL Syntax: <scheme>://<host>:<port>/<path>;<params>?<query>#<frag>
http://www.wlw.com/test/go;type=s
vim /etc/haproxy/haproxy.cfg frontend main *:80 default_backend webserver backend webserver balance uri hash-type consistent server web.ip45 192.168.0.45:80 check server web.ip66 192.168.0.66:80 check
为了测试出结果。咱们为web1和web2各提供五个页面供测试
[root@wlw1 ~]# for i in {1..5};do echo "Page $i from web.ip45" > /var/www/html/page$i.html;done [root@wlw2 ~]# for i in {1..5};do echo "Page $i from web.ip66" > /var/www/html/page$i.html;done
这里咱们使用三个客户端来测试结果,能够看到只要是访问同一个uri都是调度到同一台服务器上
[root@localhost ~]# curl http://192.168.0.56/page1.html Page 1 from web.ip66 [root@wlw1 ~]# curl http://192.168.0.56/page1.html Page 1 from web.ip66 [root@wlw2 ~]# curl http://192.168.0.56/page1.html Page 1 from web.ip66 [root@localhost ~]# curl http://192.168.0.56/page4.html Page 4 from web.ip45 [root@wlw1 ~]# curl http://192.168.0.56/page4.html Page 4 from web.ip45 [root@wlw2 ~]# curl http://192.168.0.56/page4.html Page 4 from web.ip45
url_param:经过<argument>为URL指定的参数在每一个HTTP GET请求中将会被检索;若是找到了指定的参数且其经过等于号“=”被赋予了一个值,那么此值将被执行hash运算并被服务器的总权重相除后派发至某匹配的服务器;此算法能够经过追踪请求中的用户标识进而确保同一个用户ID的请求将被送往同一个特定的服务器,除非服务器的总权重发生了变化;若是某请求中没有出现指定的参数或其没有有效值,则使用轮叫算法对相应请求进行调度;此算法默认为静态的,不过其也可使用hash-type修改此特性;
hdr(<name>):对于每一个HTTP请求,经过<name>指定的HTTP首部将会被检索;若是相应的首部没有出现或其没有有效值,则使用轮叫算法对相应请求进行调度;其有一个可选选项“use_domain_only”,可在指定检索相似Host类的首部时仅计算域名部分(好比经过www.magedu.com来讲,仅计算magedu字符串的hash值)以下降hash算法的运算量;此算法默认为静态的,不过其也可使用hash-type修改此特性;
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg frontend main *:80 default_backend webserver backend webserver balance hdr(User-Agent) hash-type consistent server web.ip45 192.168.0.45:80 check server web.ip66 192.168.0.66:80 check
这里咱们使用curl的选项-A来模拟不一样浏览器,测试咱们根据用户浏览器类型来调度到不一样的服务器
[root@localhost ~]# curl -A 'Google' http://192.168.0.56/index.html My web2 192.168.0.66 [root@localhost ~]# curl -A 'IE 6' http://192.168.0.56/index.html My web1 192.168.0.45
②、hash-type <method>
定义用于将hash码映射至后端服务器的方法;其不能用于frontend区段;可用方法有map-based和consistent,在大多数场景下推荐使用默认的map-based方法。
map-based:hash表是一个包含了全部在线服务器的静态数组。其hash值将会很是平滑,会将权重考虑在列,但其为静态方法,对在线服务器的权重进行调整将不会生效,这意味着其不支持慢速启动。此外,挑选服务器是根据其在数组中的位置进行的,所以,当一台服务器宕机或添加了一台新的服务器时,大多数链接将会被从新派发至一个与此前不一样的服务器上,对于缓存服务器的工做场景来讲,此方法不甚适用。
consistent:hash表是一个由各服务器填充而成的树状结构;基于hash键在hash树中查找相应的服务器时,最近的服务器将被选中。此方法是动态的,支持在运行时修改服务器权重,所以兼容慢速启动的特性。添加一个新的服务器时,仅会对一小部分请求产生影响,所以,尤为适用于后端服务器为cache的场景。不过,此算法不甚平滑,派发至各服务器的请求未必能达到理想的均衡效果,所以,可能须要不时的调整服务器的权重以得到更好的均衡性。
③、bind:此指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字。
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg frontend main bind *:80 bind *:8989 [root@localhost ~]# ss -tnlp [root@localhost ~]# ss -tnlp State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:80 *:* users:(("haproxy",2146,5)) LISTEN 0 128 *:8989 *:* users:(("haproxy",2146,6))
④、mode: HAProxy的工做模式;默认为tcp;还有基于web应用的http
⑤、为每一个实例启用事件和流量日志,所以可用于全部区段。每一个实例最多能够指定两个log参数,不过,若是使用了“log global”且"global"段已经定了两个log参数时,多余了log参数将被忽略。
⑥、maxconn:设定一个前端的最大并发链接数,所以,其不能用于backend区段。对于大型站点来讲,能够尽量提升此值以便让haproxy管理链接队列,从而避免没法应答用户请求。固然,此最大值不能超出“global”段中的定义。
⑦、default_backend:在没有匹配的"use_backend"规则时为实例指定使用的默认后端,所以,其不可应用于backend区段。在"frontend"和"backend"之间进行内容交换时,一般使用"use-backend"定义其匹配规则;而没有被规则匹配到的请求将由此参数指定的后端接收。
⑧、server:为后端声明一个server,所以,不能用于defaults和frontend区段。
server <name> <addr>[:port] [param*]
backup: 设定当前server为backup server;
check: 健康状态检测;
inter <delay>:检测时间间隔;单位为ms, 默认为2000;
fall: up --> down, soft state, soft state, hard state;
rise:down --> up,
后端http服务时的健康状态的检测方法:
option httpchk:请求首页,对方响应200即为成功
option httpchk <uri>:指定的uri,对方响应200即为成功
option httpchk <method> <uri>:指定方法和uri
option httpchk <method> <uri> <version>:不能用于frontend段
backend https_relay mode tcp option httpchk OPTIONS * HTTP/1.1\r\nHost:\ #使用OPTINOS方法请求,请求uriHTTP/1.1\r\nHost:\ www.wlw.com server web1 192.168.0.88:443 check port 80 #转发服务器为192.168.0.88:443,请求443端口。然而能够对80端口作检测
cookie <value>:为指定server设定cookie值,此处指定的值将在请求入站时被检查,第一次为此值挑选的server将在后续的请求中被选中,其目的在于实现持久链接的功能;基于cookie会话的源绑定。
maxconn: 此服务接受的并发链接的最大数量;
maxqueue: 请求队列的最大长度;
observe: 根据流量判断后端server的健康状态;
weight: 指定权重,默认为1,最大为256;0表示不被调度,即为下线。
redir <prefix>: 启用重定向功能,将发往此服务器的GET和HEAD请求均以302状态码响应;须要注意的是,在prefix后面不能使用/,且不能使用相对地址,以避免形成循环
server web1 192.168.0.88:80 redir http://img.wlw.com check
⑨、stats:启用基于程序编译时默认设置的统计报告,不能用于“frontend”区段。
listen stats bind *:1515 #让stats统计报告监听在1515端口上 stats enable #开启stats功能 stats hide-version #隐藏版本信息 stats uri /hpadmin?stats #设置uri stats realm HAporxy\ admin #开启认证时登陆框显示的信息 stats auth wlw:wlw #认证的帐号密码 stats auth test:test stats admin if TRUE #若是上面条件认证经过,开启管理接口 stats scope . #仅能为127.0.0.1本地访问
⑩、option forwardfor:容许在发往服务器的请求首部中插入“X-Forwarded-For”首部。
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg defaults option forwardfor except 127.0.0.0/8 [root@wlw ~]# vim /etc/httpd/conf/httpd.conf LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined #为http访问日志中的主机替换为发送客户端首部的真实IP地址 [root@wlw ~]# tail /var/log/httpd/access_log 192.168.0.102 - - [25/Oct/2015:05:48:43 +0800] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"
11、errorfile:在用户请求不存在的页面时,返回一个页面文件给客户端,这里可用的状态码有200、400、40三、40八、500、50二、503和504;
errorfile 503 /etc/haproxy/errorpages/503sorry.http
12、添加请求或响应报文首部:reqadd,请求报文发完server的时候添加。rspadd,响应报文发给客户端的时候添加。
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg frontend main bind *:8989 bind *:80 default_backend webserver rspadd Via:\ 192.168.0.56 [root@localhost ~]# curl -I http://192.168.0.56 HTTP/1.1 200 OK Via: 192.168.0.56
6、Haproxy实现LAMP动静分离
[root@localhost system]# vim /etc/haproxy/haproxy.cfg frontend http bind *:80 mode http acl url_static path_beg -i /static /p_w_picpaths /javascript /stylesheets acl url_static path_end -i .htm .jpg .jpeg .gif .png .css .js use_backend static_servers if url_static default_backend dynamic_servers backend static_servers balance roundrobin server web_static 192.168.0.45:80 check backend dynamic_servers cookie srv insert nocache balance roundrobin server web_dynamic 192.168.0.66:80 check cookie dynamic
在浏览器中经过开发工具查看
测试把192.168.0.66的httpd关闭。由于192.168.0.66是响应动态页面的服务器,因此关闭后php页面没法响应,可是访问图片正常