引言:工作中多次用到HAProxy实现负载均衡、会话保持和健康检查以及send-proxy,在此将学习到的相关知识写成笔记。其中,参照了很多大神的文章进行探究,特此感谢,参照的文章见下:
https://blog.csdn.net/genglei1022/article/details/83374188
https://www.cnblogs.com/chimeiwangliang/p/8042190.html
https://cloud.tencent.com/info/123ec0e0263886bd708618504a026922.html
http://www.cnblogs.com/f-ck-need-u/p/8502593.html
https://www.cnblogs.com/zhengchunyuan/p/10094916.html
HAProxy使用C语言编写的开放源代码软件,提供高可用性、负载均衡,以及基于TCP(4层)和HTTP(7层)的应用程序代理;
借助HAProxy可以快速并可靠的提供基于TCP和HTTP应用的代理解决方案,并支持虚拟主机;
HAProxy实现了一种时间驱动,单一进程模型,此模型支持非常大的链接数;
HAProxy支持拒绝连接:维护连接开销低,可以限制攻击蠕虫(attack bots),该功能拯救了很多被DDos攻击的小型站点;
HAProxy支持全透明代理(具备防火墙的典型特点):可以用客户端IP地址或者任何其他地址来连接后端服务器. 这个特性仅在Linux 2.4/2.6内核打了cttproxy补丁后才可以使用. 这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。
通过负载均衡算法, HAproxy能够接受数以万计的访问请求并将其转发到后端服务器池中进行处理,而后端服务器池就如一个强大的虚拟服务器接受 HAProxy转发的请求并进行处理。 HAproxy的请求调度器(Scheduler)决定了后端服务器中每个服务器接受和处理的请求量,在没有权重的调度算法下,调度器为每台服务器分配相同数量的请求,而在加权调度算法下,调度器根据每台服务器的权重为每个后端服务器分配不同数量的请求。
HAProxy允许用户自定义多个代理,并为每个代理提供负载均衡服务,代理由一个前端和一个或多个后端构成,前端定义了代理监听的IP地址(Virtual IP )和端口,同时还需在前端定义中关联与其相关的后端,而在HAProxy中,后端主要用于定义服务器池和负载均衡算法。HAProxy的负载均衡服务在7层,即应用层,在很多情况下,由于商业应用连续性的要求,管理员通常需要部署HAProxy,从而为基于HTTP的应用提供负载均衡和高可用性。
没有负载均衡的简单Web应用程序环境可能如下所示:
用户直接连接到您的Web服务器,在yourdomain.com上,并且没有负载平衡。如果单个Web服务器出现故障,用户将无法再访问Web服务器。此外,如果许多用户试图同时访问服务器并且无法处理负载,他们可能会遇到缓慢的体验,或者可能根本无法连接。
4层负载均衡:将网络流量负载平衡到多个服务器的最简单方法是使用第4层(传输层)负载平衡。以这种方式进行负载均衡将根据IP范围和端口转发用户流量(即,如果请求进入http://yourdomain.com/anything,则流量将转发到处理yourdomain.com的所有请求的后端。端口80)。
用户访问负载均衡器,负载均衡器将用户的请求转发给后端服务器的Web后端组。无论选择哪个后端服务器,都将直接响应用户的请求。通常,Web后端中的所有服务器应该提供相同的内容 - 否则用户可能会收到不一致的内容。
7层负载均衡:7层负载均衡是更复杂的负载均衡网络流量的方法是使用第7层(应用层)负载均衡。使用第7层允许负载均衡器根据用户请求的内容将请求转发到不同的后端服务器。这种负载平衡模式允许您在同一域和端口下运行多个Web应用程序服务器。
如果用户请求yourdomain.com/blog,则会将其转发到博客后端,后端是一组运行博客应用程序的服务器。其他请求被转发到web-backend,后端可能正在运行另一个应用程序。
HAProxy的配置文件是/etc/haproxy/haproxy.cfg,该文件是 HAProxy功能配置的集中文件,其代理和负载均衡功能的配置均位于该配置文件中。 HAProxy的配置文件主要分为四个部分,即全局功能配置段global、默认属性配置段defaults、前端代理配置段frontend、后端负载均衡配置段backend。代理配置段。包括defaults
,listen
,frontend
和backend
段
所有的
在配置文件中,一些包含了数值的参数表示时间,如timeout。这些值默认以毫秒为单位,但也可以使用其它的时间单位后缀。
可以使用haproxy命令行检查配置文件语法是否正确。
haproxy -f /etc/haproxy/phaproxy.cfg -c
或者使用sysv脚本的check参数。
service haproxy check
1)进程及安全配置相关的参数
log [max level [min level]]
2)性能调整参数
因此,抛去不建议设置的项后,global段的设置大致如下:这也是yum安装haproxy时默认提供的配置
global
daemon
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
stats socket /var/lib/haproxy/stats
注意上面配置了使用local2记录log,因此还需去rsyslogd的配置文件中添加该设备以及记录的日志位置。如下:
cat <>/etc/rsyslog.conf
local2.* /var/log/haproxy.log
eof
默认(default)配置段设置的参数会被haproxy.cfg的其他配置段继承,如frontend、backend和 listen配置段都会继承 default配置段参数,同时这些配置段也可以写default配置段的参数值,通常情况下,用户可以将具有共性的参数放到default段进行统一配置,然后再到各个配置段中进行个性修改,
一般来说,对于高速局域网络来说,如果后端响应的速度非常快(比如后端是静态服务器响应小文件、后端是静态缓存服务器),这时建立tcp连接的代价就比较大,维持空闲连接的优势会非常明显。如果后端是动态应用程序,响应给haproxy的速度相对较慢,维持空闲连接的代价非常大,完全可以先释放长连接以腾出资源,在需要连接的时候再建立新tcp连接。因此:
(1).后端是静态内容缓存服务器时,或者就是静态服务器时,首选使用http-keep-alive模式;
(2).后端是动态应用程序服务器时,首选使用http-server-close模式。
默认情况下,如果客户端请求根据调度算法被调度到另一台后端服务器时,http-keep-alive模式下和后端服务器的空闲连接会立即断开,并重新和被调度选中的后端服务器建立连接。可以使用"prefer-last-server"选项,使得haproxy先查看当前保持的空闲连接是否可用,如果可用,则继续使用该空闲连接,但是这样会影响调度性能。
frontend和backend都可以设置这些模式选项,如果它们交叉设置了,最终何种模式会生效?例如,frontend设置了http-keep-alive,而bakcend设置了http-server-close时,取何种模式?计算方式采用如下矩阵:keepalive优先级是最弱的,forceclose是优先级是最高的。
格式:balance
定义负载均衡算法,可用于“defaults”、“listen”和“backend”。用于在负载均衡场景中挑选一个server,其仅应用于持久信息不可用的条件下或需要将一个连接重新派发至另一个服务器时。常用的算法有:
roundrobin和static-rr是有区别的,roundrobin是动态慢轮询,不用重启服务即可调整其权重,而static-rr必须重启服务修改的权重才生效。例如原有2台后端server,新添加一台后,roundrobin会从此时开始慢慢的将请求轮询至此新服务器,而static-rr由于需要重启,所以重启前新server不会被调度到,重启后新server和旧server平均调度。一般来说,考虑加权轮询的时候,roundrobin要比static-rr好。
一般可纳入考虑的算法有roundrobin/static-rr/leastconn/uri,其中leastconn算法用于代理ldap、mysql等长时间会话连接的情况,uri算法用于代理后端为缓存服务器的情况。
(1). 用于调度MySQL服务器,使用何种算法?答:leastconn
(2). 用于调度静态服务器组,使用何种算法?答:roundrobin
(3). 调度动态应用程序服务器组,使用何种算法?答:通常客户端需要和后端应用程序服务器保持联系,一般会使用cookie或者session来实现,但如果特殊情况下无法通过它们实现,则可以使用source作为最后"亲和性"手段。注意,使用source算法时,后端服务器数量一改变,就会导致大量的会话断开。
(4). 调度缓存服务器,使用何种算法?答:uri,且设置hash-type为一致性哈希算法。
格式:bind \[\]: [, ...] [param*]
此指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字。
:可选项,可以为主机名、IPv4地址、IPv6地址或*;省略此选项、将其指定为*或0.0.0.0时,将监听当前系统的所有IPv4地址;
:可以是一个特定的TCP端口,也可是一个端口范围(如5005-5010),代理服务器将通过指定的端口来接收客户端请求;注意,小于1024的端口需要有特定权限的用户才能使用;
:指定物理接口的名称;格式:mode { tcp|http|health }
设定实例的运行模式或协议。当实现内容交换时,前端和后端必须工作于同一种模式(一般说来都是HTTP模式),否则将无法启动实例。
格式:hash-type
定义用于将hash码映射至后端服务器的方法;其不能用于frontend区段;可用方法有map-based和consistent,在大多数场景下推荐使用默认的map-based方法。
格式:
log global
log [ [] ]
为每个实例启用事件和流量日志,因此可用于所有区段。每个实例最多可以指定两个log参数,不过,如果使用了“log global”且”global”段已经定了两个log参数时,多余了log参数将被忽略。
格式:maxconn
设定一个前端的最大并发连接数,因此,其不能用于backend区段。对于大型站点来说,可以尽可能提高此值以便让haproxy管理连接队列,从而避免无法应答用户请求。当然,此最大值不能超出“global”段中的定义。此外,需要留心的是,haproxy会为每个连接维持两个缓冲,每个缓冲的大小为8KB,再加上其它的数据,每个连接将大约占用17KB的RAM空间。这意味着经过适当优化后,有着1GB的可用RAM空间时将能维护40000-50000并发连接。
如果为
格式:server
为后端声明一个server,因此,不能用于defaults和frontend区段。
:此服务器的的IPv4地址,也支持使用可解析的主机名,只不过在启动时需要解析主机名至相应的IPv4地址;
[:port]:指定将连接请求所发往的此服务器时的目标端口,其为可选项;未设定时,将使用客户端请求时的同一相端口;
[param*]:为此服务器设定的一系参数;其可用的参数非常多,具体请参考官方文档中的说明,下面仅说明几个常用的参数;
服务器或默认服务器参数:
关于maxconn和maxqueue,这两个值都是此后端服务器的值。它们的大小和全局定义的maxconn是有一定大小比较关系的。如果没有定义maxqueue,则全局maxconn应该小于或等于后端所有服务器的maxconn之和,如果定义了maxqueue,则需要小于或等于后端所有服务器的maxconn和maxqueue之和。否则haproxy接收进来的请求超过后端服务器的压力极限,可能压垮后端。
option forwardfor [ except ] [ header ] [ if-none ]
允许在发往服务器的请求首部中插入"X-Forwarded-For"首部。
except
:可选参数,当指定时表示请求中的源地址能匹配此网络时禁用此功能。header
:可选参数,自定义首部名,如"X-Client"来替代"X-Forwarded-For"。有些独特的web服务器的确需要一个独特的首部。if-none
:仅在此首部不存在时才将其添加至请求报文问道中。HAProxy工作于反向代理模式,其发往服务器的请求中的客户端IP均为HAProxy主机的地址而非真正客户端的地址,这会使得服务器端的日志信息记录不了真正的请求来源,"X-Forwarded-For"首部则可用于解决此问题。HAProxy可以向每个发往服务器的请求上添加此首部,并以客户端IP为其value。
下面是一个例子。
frontend www
mode http
option forwardfor except 127.0.0.1
option httpchk
option httpchk
option httpchk
option httpchk
不能用于frontend段。
此指令表示基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康。不设置该选项时,默认采用tcp做健康检查,只要能建立tcp就表示健康。
uri
:检查的uri路径,默认为"/"。接受带有查询参数的urimethod
:http检查时使用的METHOD。不指定时默认为"OPTIONS"方法,也建议采用此方法,因为该请求方法对服务器造成的资源损耗最小。version
:检查的http协议版本,默认为http/1.0,但现在很多都采用HTTP/1.1,因此此处检查版本需要修改为HTTP/1.1,但对于该版本的HTTP协议来说,还强制要求指定Host,中间使用\r\n
隔离。例如下面的配置,会将健康检查时的页面请求发送至后端192.168.1.1的80端口来确定该后端是正常的,但客户端的请求将转发至该后端的443端口。
backend https_relay
mode tcp
option httpchk
option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
server apache1 192.168.1.1:443 check port 80
stats enable
:启用基于程序编译时默认设置的统计报告,不能用于"frontend"区段。只要没有另外的其它设定,默认就会使用如下的配置:
- stats uri : /haproxy?stats
- stats realm : "HAProxy Statistics"
- stats auth : no authentication
- stats scope : no restriction
尽管"stats enable"一条就能够启用统计报告,但还是建议设定其它所有的参数,以免依赖于默认设定而带来非预期后果。
例如:
backend public_www
server websrv1 172.16.100.11:80
stats enable
stats hide-version
stats scope .
stats uri /haproxyadmin?stats
stats realm Haproxy\ Statistics
stats auth statsadmin:password
stats auth statsmaster:password
stats hide-version
:启用统计报告并隐藏HAProxy版本报告,不能用于"frontend"区段。stats realm
:stats auth身份认证时的提示信息。设置的提示信息中,如果有空白字符,则需要转义。仅在与"stats auth"配合使用时有意义。stats auth
:启用带认证的统计报告功能并授权一个用户帐号和对应的密码(明文)。也就是说,想要查看统计报告需要提供身份和密码。不能用于"frontend"区段。stats admin
:满足指定条件时启用统计报告页面的管理功能,它允许通过web接口启用或禁用后端服务器。 stats admin { if | unless }
下面是两个案例,第一个限制了仅能在本机打开报告页面时启用管理功能,第二个定义了仅允许通过认证的用户使用管理功能。
backend stats_localhost
stats enable
stats admin if LOCALHOST
backend stats_auth
stats enable
stats auth haproxyadmin:password
stats admin if TRUE
在backend服务器组启用cookie功能,以便实现cookie绑定。需要同时设置server指令中的cookie选项。
后端为静态服务器设置:
cookie NAME insert nocache
PHP做后端时设置:
cookie SESSION_COOKIE insert indirect nocache
当客户端绑定cookie对应的后端服务器宕机后,应该为此客户端重新调度一个后端server,否则将打不开页面。这时需要使用option redispatch,表示当找不到cookie对应的服务器时分配新的服务器给客户端。
时间单位默认都是毫秒。
acl [flags] [operator] [] ...
aclname:指定acl的名称,在引用时区分大小写。可随意指定,且多个acl指令可以指定同一个aclname,这表示"或"的逻辑关系。
flags:可选项,表示标识位。一般会用到的标识位只有"-i",表示不区分大小写。
operator:可选项,某些操作符,有"eq"、"ge"、"gt"、"le"、"lt",表示数学上的等于、大于、小于。
:指定检查标准,即检查方法。见下文给出的常用4层标准和7层标准
value:根据criterion的不同,值的类型不同。
(1).4层常用检查标准,官方手册:https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7.3.3
src
src_port
dst
dst_port
其中src、src_port、dst和dst_port就是检查标准creiterion,其后的值就是value。
例如:
acl accept_clients src 192.168.100.0/24
acl reject_clients src 172.16.0.0/16
tcp-request content accept if accept_clients
tcp-request content reject if reject_clients
tcp-request content reject # 此项表明不匹配前两项的默认都拒绝
(2).7层常用检查标准,官方手册:https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#7.3.6
hdr(Connection) -i close
表示首部字段Connection的值是否为不区分大小写的close。hdr(Host) -i www.longshuai.com
表示首部字段Host的值是否为www.longshuai.com
,即请求的主机是否是指定的值。hdr_reg(Host) -i .*\.longshuai\.com
。acl valid_method method GET
http-request deny if ! valid_method
path -i /a.png
。还有很多很多检查方法,更多的查询官方手册,太多了。一般4层的检查标准和7层对路径path和首部hdr的标准就够了。
多个条件使用"AND"、"OR"、"!"操作符表示逻辑与、逻辑或和取反,不写时默认的操作符是"AND"。
acl url_static path_beg /static /images /img /css /viedo /download # 定义静态检查标准
acl url_static path_end .gif .png .jpg .css .js .bmp # 定义静态检查标准
acl host_www path /index.html # 为主页专门定制acl
acl url_dynamic path_end .php .php5 # 定义动态检查标准
acl host_www hdr_beg(Host) -i www.longshuai.com # 定位到主页
use_backend static if url_static
use_backend dynamic if url_dynamic
use_backend www if host_www
本文非原创,转载请注明原文地址!