一、haproxy 说明
二、haproxy 连接模式说明
三、haproxy 调度方法说明
四、hash-type 说明
五、架构说明
六、基本安装及配置说明(roundrobin调度)
七、URI调度测试
八、HDR调度测试
九、基于cookie的session绑定测试
十、状态页面测试
(参数说明来自官网,如有出入,以官网为主)
一、HAProxy说明
(1)HAProxy是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。 HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的 并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
(2)HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。
(3)HAProxy 支持连接拒绝 : 因为维护一个连接的打开的开销是很低的,有时我们很需要限制攻击蠕虫(attack bots),也就是说限制它们的连接打开从而限制它们的危害。 这个已经为一个陷于小型DDoS攻击的网站开发了而且已经拯救
了很多站点,这个优点也是其它负载均衡器没有的。
(4)HAProxy 支持全透明代理(已具备硬件防火墙的典型特点): 可以用客户端IP地址或者任何其他地址来连接后端服务器. 这个特性仅在Linux 2.4/2.6内核打了cttproxy补丁后才可以使用. 这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。
性能说明
HAProxy借助于OS上几种常见的技术来实现性能的最大化。
1,单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。
2,O(1)事件检查器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测。
3,在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽;
4,借助于Linux 2.6 (>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting);
5,内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长;
6,树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;
7,优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;
8,精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;
所有的这些细微之处的优化实现了在中等规模负载之上依然有着相当低的CPU负载,甚至于在非常高的负载场景中,5%的用户空间占用率和95%的系统空间占用率也是非常普遍的现象,这意味着HAProxy进程消耗比系统空间消耗低20倍以上。因此,对OS进行性能调优是非常重要的。即使用户空间的占用率提高一倍,其CPU占用率也仅为10%,这也解释了为何7层处理对性能影响有限这一现象。由此,在高端系统上HAProxy的7层性能可轻易超过硬件负载均衡设备。
在生产环境中,在7层处理上使用HAProxy作为昂贵的高端硬件负载均衡设备故障故障时的紧急解决方案也时长可见。硬件负载均衡设备在"报文"级别处理请求,这在支持跨报文请求(request across multiple packets)有着较高的难度,并且它们不缓冲任何数据,因此有着较长的响应时间。对应地,软件负载均衡设备使用TCP缓冲,可建立极长的请求,且有着较大的响应时间。
二、haprox连接模式
haproxy支持5种连接模式:
keep alive:是默认模式:处理所有请求和响应,连接保持打开,但在响应和新请求之间空闲。
tunnel:这是版本1.0到1.5-dev21的默认模式:只有第一个请求和响应被处理,其他的都被转发,根本没有分析。不应使用此模式,因为它会对日志记录和HTTP处理造成很多麻烦。
passive close(被动关闭):与隧道模式完全相同,但在连个方向上添加"Connection: close"以尝试在第一次交换之后使两端关闭。
server close(服务器关闭):面向服务器连接在收到响应结束后关闭,但是面向客户端的连接保持打开。
forced close(强制关闭):连接被主动关闭后的响应结束。
三、haproxy调度方法
roundrobin:每个服务器根据其权重轮流使用。当服务器的处理时间保持均匀分布时,这是最平滑和最公平的算法。该算法是动态的,这意味着服务器权重可以例如在慢启动时被即时调整。它由设计限制为每个后端4095个活动服务器。请注意,在一些大型服务器场中,当服务器在停机很短时间后出现故障时,有时可能需要几百个请求才能重新集成到服务器场并开始接收流量。这是正常的,虽然很罕见。它在这里指示的情况下,你会有机会观察它,所以你不要担心。
static-rr:每个服务器轮流使用,根据其权重。此算法与roundrobin类似,除了它是静态的,这意味着即时更改服务器的权重将没有任何效果。另一方面,它对服务器数量没有设计限制,并且当服务器上升时,一旦重新计算完整映射,它总是立即被重新引入到场中。它还使用稍少的CPU运行(约-1%)。
leastconn:具有最低连接数的服务器接收连接。循环在相同负载的服务器组内执行,以确保将使用所有服务器。建议在期望非常长的会话(例如LDAP,SQL,TSE等)的情况下使用此算法,但不是非常适合使用短会话(例如HTTP)的协议。该算法是动态的,这意味着服务器权重可以例如在慢启动时被即时调整。
first:具有可用连接槽的第一台服务器接收连接。服务器从最低的数字标识符到最高(参见服务器参数"id"),默认为服务器在服务器场中的位置。一旦服务器达到其maxconn值,将使用下一个服务器。使用此算法没有设置maxconn没有意义。此算法的目的是始终使用最小数量的服务器,以便在非密集时间内可关闭额外的服务器。此算法忽略服务器权重,并且对长会话(例如RDP或IMAP)比HTTP带来更多好处,虽然它也可以是有用的。为了有效地使用此算法,建议云控制器定期检查服务器使用情况,在未使用时将其关闭,并定期检查后端队列以在队列膨胀时打开新服务器。或者,使用"http检查发送状态"可以通知负载上的服务器.
source:源IP地址被散列并除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这确保相同的客户端IP地址将始终到达相同的服务器,只要没有服务器关闭或启动。如果散列结果由于正在运行的服务器数量而更改,则许多客户端将被定向到不同的服务器。此算法通常用于不能插入cookie的TCP模式。它还可以在网络上使用以向拒绝会话cookie的客户端提供尽力而为的粘性。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将没有效果,但可以使用"哈希类型"更改。
uri:该算法对URI的左侧部分(问号之前)或整个URI(如果存在"整体"参数)进行散列,并将散列值除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这确保了只要没有服务器启动或关闭,相同的URI将始终被定向到同一服务器。这与代理缓存和反病毒代理一起使用,以便最大化缓存命中率。请注意,此算法只能在HTTP后端中使用。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将没有效果,但可以使用"哈希类型"更改。
该算法支持两个可选参数"len"和"depth",两者后跟一个正整数。当需要仅基于URI的开始来平衡服务器时,这些选项可能有所帮助。 "len"参数指示算法应该仅考虑在URI的开始处的许多字符以计算散列。请注意,将"len"设置为1很少有意义,因为大多数URI以前导"/"开头。
"depth"参数指示要用于计算散列的最大目录深度。对请求中的每个斜杠计数一个级别。如果指定了两个参数,当达到任何一个时,评估将停止。
url_param:参数中指定的URL参数将在每个HTTP GET请求的查询字符串中查找。
如果使用修饰符"check_post",那么当在URL中的问号('?')之后的查询字符串中找不到参数参数时,将搜索HTTP POST请求实体。只有在接收到通告的数据量或请求缓冲区已满时,才会开始分析消息体。在不太可能发生的情况下,使用分块编码,只扫描第一个块。由块边界分隔的参数值可以是随机平衡的,如果有的话。此关键字用于支持可选的<max_wait>参数,该参数现在被忽略。
如果找到参数后跟有等号('=')和值,那么该值将被哈希并除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。
这用于跟踪请求中的用户标识符,并确保只要没有服务器上下移动,相同的用户ID将始终发送到同一服务器。如果没有找到值或者没有找到参数,则应用循环算法。请注意,此算法只能在HTTP后端中使用。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将没有效果,但可以使用"哈希类型"更改。
hdr:将在每个HTTP请求中查找HTTP标头<name>。与等效ACL'hdr()'函数一样,括号中的头名称不区分大小写。如果头不存在或者如果它不包含任何值,则应用roundrobin算法。
可选的"use_domain_only"参数可用,用于将散列算法减少到具有一些特定头部(例如"主机")的主域部分。例如,在主机值"haproxy.1wt.eu"中,将仅考虑"1wt"。
默认情况下,此算法是静态的,这意味着即时更改服务器的权重将没有效果,但可以使用"哈希类型"更改。
rdp-cookie:将为每个传入的TCP请求查找和哈希RDP cookie<name>(或如果省略,则为"mstshash")。 与等效ACL"req_rdp_cookie()"函数一样,名称不区分大小写。此机制作为降级的持久性模式是有用的,因为它使得可以总是向同一服务器发送相同的用户(或相同的会话ID)。如果没有找到cookie,则使用正常的roundrobin算法。注意,为了这个工作,前端必须确保RDPcookie已经存在于请求缓冲区中。为此,您必须使用'tcp-request内容接受'规则结合'req_rdp_cookie_cnt'ACL。 默认情况下,此算法是静态的,这意味着即时更改服务器的权重将没有效果,但可以使用"哈希类型"更改。另请参见rdp_cookie模式提取函数。
四、hash-type说明
map-based:哈希表是包含所有活动服务器的静态数组。哈希将非常流畅,将考虑权重,但将是静态的,在权重变化,而服务器启动将被忽略。这意味着没有慢的开始。此外,由于服务器通过其在数组中的位置来选择,所以当服务器计数改变时,大多数映射被改变。这意味着,当服务器启动或关闭时,或者服务器添加到场时,大多数连接将重新分发到不同的服务器。这对于例如缓存是不方便的。
consistent:哈希表是一个填充了每个服务器的许多出现的树。在树中查找散列密钥,并选择最接近的服务器。此哈希是动态的,它支持在服务器启动时更改权重,因此它与慢启动功能兼容。它的优点是,当服务器上移或下移时,只会移动其关联。将服务器添加到服务器场时,只会重新分配一小部分映射,这使它成为高速缓存的理想方法。然而,由于其原理,分布将永远不会非常平滑,并且有时可能需要调整服务器的权重或其ID以获得更平衡的分布。为了在多个负载平衡器上获得相同的分配,所有服务器都必须具有完全相同的ID。注意:如果未指定散列函数,则一致散列使用sdbm和avalanche。
五、架构说明
六、基本安装及配置说明(roundrobin调度)
6.1.添加用户
# groupadd -g 200 haproxy # adduser -u 200 -g 200 -s /sbin/nologin haproxy
6.2.安装
yum install haproxy
6.3.配置文件说明
global log 127.0.0.1 local2 #记录日志 chroot /var/lib/haproxy #chroot的路径 pidfile /var/run/haproxy.pid #pid文件 maxconn 4000 #最大连接数 user haproxy #运行用户 group haproxy #运行用户组 daemon #守护进程运行 stats socket /var/lib/haproxy/stats defaults mode http #工作模式,支持TCP、http、health log global #使用global的日志 option httplog #启用HTTP请求,会话状态和计时器的日志记录 option dontlognull #启用空连接不记录日志 option http-server-close #在服务器端启用HTTP连接关闭 option forwardfor except 127.0.0.0/8 #启用向发送到服务器的请求头插入X-Forwarded-For标记 option redispatch #在连接失败的情况下启用会话重新分配 retries 3 #设置在连接失败后在服务器上执行的重试次数 timeout http-request 10s #设置等待完整HTTP请求的最长允许时间 timeout queue 1m #设置队列中等待连接池空闲的最长时间 timeout connect 10s #设置等待连接尝试到服务器成功的最长时间。 timeout client 1m #设置客户端的最长不活动时间 timeout server 1m #设置服务器端的最长不活动时间。 timeout http-keep-alive 10s #设置当一个新的HTTP请求出现时,允许的最大请求时间 timeout check 10s #设置其他检查超时,但只有在连接已经存在之后建立 maxconn 3000 #设置最大套接字连接数 frontend main *:80 use_backend webserver #定义使用的后端的服务器组 backend webserver balance roundrobin #定义使用的调度模式 server ckl1 172.16.110.47:80 check server ckl1 172.16.110.48:80 check server ckl1 172.16.110.49:80 check
启动进程:
systemctl start haproxy.service
6.4.在126、194、180上面添加页面,测试访问
七、URI调度测试
7.1.修改haproxy配置文件
vim /etc/haproxy/haproxy.cfg ..... backend webserver balance uri #uri调度方式 hash-type consistent #一致性hash算法 server web1 192.168.199.126:80 check server web2 192.168.199.194:80 check server web3 192.168.199.180:80 check
7.2.重新加载服务
systemctl reload haproxy.service
7.3.测试访问新页面
经过测试发现,始终调度到同一台后端服务器上
八、HDR调度测试
8.1.官网示例:
balance roundrobin balance url_param userid balance url_param session_id check_post 64 balance hdr(User-Agent) balance hdr(host) balance hdr(Host) use_domain_only
hdr:根据请求头中的字段进行调度
8.2.hdr(host)调度
修改配置文件
vim /etc/haproxy/haproxy.cfg ..... backend webserver balance hdr(host) #hdr调度方式 hash-type consistent #一致性hash算法 server web1 192.168.199.126:80 check server web2 192.168.199.194:80 check server web3 192.168.199.180:80 check
8.3.hdr(host)测试访问
重新加载服务:
systemctl reload haproxy.service
测试访问:
经测试发现,请求调度到后端同一台服务器
8.4.hdr(User-Agent)调度
vim /etc/haproxy/haproxy.cfg ..... backend webserver balance hdr(User-Agent) hash-type consistent server web1 192.168.199.126:80 check server web2 192.168.199.194:80 check server web3 192.168.199.180:80 check
重新加载服务:
systemctl reload haproxy.service
8.5.hdr(User-Agent)测试访问
经测试,发现不同的客户端,调度到不同的后端服务器
九、session绑定测试
9.1.server和默认选项说明
server <name> <address>[:port] [settings ...]
backup:设置为备份服务,当其他服务不可用时,才请求次服务器
<name>:自定义名称
<address>:IP地址
[:port]:端口
check:启用服务器上的运行状况检查。默认情况下,服务器为始终认为可用。如果设置了"check",则服务器可用接受周期性TCP连接,以确保它真的能够服务要求
cookie:在后端启用基于Cookie的持久性。
rewrite:此关键字指示cookie将由服务器提供,并且haproxy将必须修改其值以在其中设置服务器的标识符。
insert:此关键字指示如果客户端尚未具有允许其访问此服务器的cookie,则必须由服务器响应中的haproxy插入持久性cookie。
prefix:代替响应原有的一个cookie在持久连接情景下,连接完成。indirect:指定此选项时,不会向已处理请求的服务器已有有效cookie的客户端发出cookie。如果服务器设置这样的cookie本身,它将被删除,除非"preserve"选项也设置。
nocache:当客户端和HAProxy之间存在缓存时,建议结合插入模式使用此选项,因为它确保如果需要插入cookie,可缓存响应将被标记为不可缓存。
postonly:此选项确保只会在对POST请求的响应时执行Cookie插入。它是"nocache"选项的替代选项,因为POST响应不可缓存,
因此这可确保持久性cookie永远不会被缓存。
preserve:此选项只能与"insert"和/或"indirect"一起使用。它允许服务器发出持久性cookie本身。在这种情况下,
如果在响应中找到cookie,haproxy将保持不变。这对于在注销请求之后结束持久性是有用的。
httponly:此选项告诉haproxy在插入cookie时添加"HttpOnly"cookie属性。使用此属性,以便用户代理不与非HTTP组件共享cookie。
secure:此选项告知haproxy在插入cookie时添加"安全"cookie属性。使用此属性,以便用户代理不会通过非安全通道发送此Cookie,这意味着使用此标志学习的Cookie将仅通过SSL / TLS连接显示。
domain:此选项允许指定插入Cookie的域。它只需要一个参数:有效的域名。如果域以点开头,则允许浏览器将其用于以该名称结尾的任何主机。
也可以通过多次调用此选项来指定多个域名。一些浏览器可能对域的数量有小的限制,所以在这样做时要小心。对于记录,向MSIE 6或Firefox 2发送10个域的工作原理如预期。
maxidle:此选项允许在一些空闲时间后忽略插入的Cookie。它只适用于插入模式Cookie。当Cookie发送到客户端时,发送此Cookie的日期也会发送。进一步显示此Cookie时,如果日期早于参数指示的延迟(以秒为单位),则会被忽略。否则,当响应发送到客户端时,如果需要,它将被刷新。
这对于防止从未关闭其浏览器的用户在同一服务器上保留太长时间
maxlife:此选项允许在一段时间后忽略插入的Cookie,无论它们是否正在使用。它只适用于插入模式Cookie。当Cookie首次发送到客户端时,
发送此Cookie的日期也会发送。进一步显示此Cookie时,如果日期早于参数指示的延迟(以秒为单位),则会被忽略。如果请求中的Cookie没有日期,
则接受并设置日期。将在未来超过24小时的Cookie被忽略。这样做可以让管理员修复时区问题,而不会有导致用户离开网站的风险。与maxidle相反,
此值不会刷新,只有第一个访问日期计数。maxidle和maxlife都可以在这个时候使用。这对于防止从未关闭其浏览器的用户在同一服务器上保留太长时间
例如:在服务器场大小更改后)特别有用。这比maxidle方法强,因为它在一些绝对延迟之后强制重新调度。
fall:"fall"参数说明服务器将被视为服务器宕机<count>连续失败的健康检查。如果未指定,此值默认为3。参见"check","inter"和"rise"参数。
id:设置服务器的持久性标识。此代理必须为整数,且唯一。如果未设置,将自动分配未使用的ID。第一个分配值将为1.此ID目前仅在统计信息中返回。
inter:"inter"参数将两个连续的运行状况检查之间的间隔设置为<delay>毫秒。如果未指定,延迟默认为2000ms。也可以使用"fastinter"和"downinter"来优化取决于服务器状态的检查之间的延迟.
maxconn:"maxconn"参数指定将发送到此服务器的并发连接的最大数量。如果传入的并发请求数量高于此值,则它们将排队等待连接释放。这个参数是非常重要的,因为它可以减少脆弱的服务器在极端负载下下降。如果指定了"minconn"参数,则限制变为动态。默认值为"0",表示无限制。另请参阅"minconn"和"maxqueue"参数,以及后端的"fullconn"关键字。
maxqueue:"maxqueue"参数指定将在此服务器的队列中等待的最大连接数。如果达到此限制,下一个请求将重新分配给其他服务器,而不是无限期地等待提供。这将打破持久性,但可能允许人们在尝试连接的服务器正在死亡时快速重新登录。默认值为"0",这意味着队列是无限制的。另请参见"maxconn"和"minconn"参数。
minconn:当设置"minconn"参数时,maxconn限制将成为后端加载后的动态限制。服务器将始终至少接受<minconn>连接,绝不会超过<maxconn>,并且当后端具有少于<fullconn>并发连接时,两个值之间的斜率将为限制。这使得可以在正常加载期间限制服务器上的负载,但对于重要的加载可以进一步推送它,而在异常加载期间不会使服务器过载。另请参见"maxconn"和"maxqueue"参数,以及"fullconn"后端关键字。
redir:"redir"参数为寻址此服务器的所有GET和HEAD请求启用重定向模式。这意味着,不是让HAProxy将请求转发到服务器,它将发送一个"HTTP 302"响应,带有由此前缀组成的"Location"头,紧接着是在路径组件的前导'/'处开始的请求的URI 。这意味着在<prefix>之后不应使用尾部斜杠。所有无效的请求都将被拒绝,所有非GET或HEAD请求通常由服务器提供服务。注意,由于响应是完全伪造的,所以在响应中不可能有标题管理和cookie插入。然而,仍然分析请求中的cookie,使得该解决方案完全可用于在本地灾难的情况下将用户引导到远程位置。主要用途是通过让客户端直接连接到静态服务器来增加静态服务器的带宽。注意:从不使用相对位置在这里,它会导致客户端和HAProxy之间的循环!
rise:"rise"参数表示在<count>个连续成功的运行状况检查之后,服务器将被视为可操作的。如果未指定,此值默认为2。参见"check","inter"和"fall"参数。
9.2.配置基于cookie的session绑定
vim /etc/haproxy/haproxy.cfg ..... backend webserver balance roundrobin cookie WEBSVR insert nocache server web1 192.168.199.126:80 weight 1 maxconn 500 maxqueue 300 cookie cklser1 check server web2 192.168.199.194:80 weight 1 maxconn 500 maxqueue 300 cookie cklser2 check server web3 192.168.199.180:80 weight 1 maxconn 500 maxqueue 300 cookie cklser3 check
9.3.测试访问
重新加载服务:
systemctl reload haproxy.service
测试:
经测试发现,不同浏览器带同样cookie的请求都发往同一个请求过的服务器
十、状态页面测试
10.1.修改haproxy配置文件
vim /etc/haproxy/haproxy.cfg global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 frontend main *:80 use_backend webserver frontend stats_ser #定义stats前端 bind *:8800 #定义stats监听端口 use_backend web_stats backend webserver balance roundrobin cookie WEBSVR insert nocache server web1 192.168.199.126:80 weight 1 maxconn 500 maxqueue 300 cookie cklser1 check server web2 192.168.199.194:80 weight 1 maxconn 500 maxqueue 300 cookie cklser2 check server web3 192.168.199.180:80 weight 1 maxconn 500 maxqueue 300 cookie cklser3 check backend web_stats server web1 192.168.199.126:80 check server web2 192.168.199.194:80 check server web3 192.168.199.180:80 check stats enable #开启stats功能 stats hide-version #隐藏haproxy版本信息,有益于安全 #stats scope . #作用当前域 stats uri /ckl?stats #stats页面的uri stats realm Haproxy\ Statistics #备注信息 stats auth ckl:1QAZnji9 #用户名密码 stats auth zld:4rfvBHU8 #用户名密码 stats auth admin:7uj4rf99 #用户名密码 stats admin if TRUE #不添加此项,则不开启管理员功能 stats refresh 5s #页面刷新间隔
10.2.重新加载服务
systemctl restart haproxy.service
10.3.测试状态页面: