HAProxy是由C语言编写基于事件驱动模型的一款高效稳定、功能强大的负载均衡软件,其性能可媲美商业负载均衡软件,不过在最新的版本中HAProxy已经分为社区版本和企业版,社区版完全免费,企业版有丰富的额外功能。
优缺点:
优点
缺点
HAProxy安装方式可以是yum安装或源码安装。yum安装的版本都是当前合适系统的稳定版本,个人喜欢使用yum安装。
yum install haproxy -y /#centos7默认安装版本是1.5/#主程序:/usr/sbin/haproxy/#配置文件:/etc/haproxy/haproxy.cfg/#启动服务:systemctl start haproxy/#停止服务:systemctl stop haproxy/#开机启动:systemctl enable haproxy
配置文件结构
haproxy配置文件可分为全局配置(globalsettings)和 代理配置(proxies),而代理段配置包含defaults、frontend、backend、listen。
global settings:/#全局参数配置,主要用于定义haproxy进程管理安全及性能相关的参数 defaults
配置参数可支持的时间单位
一个超级简单的WEB配置示例如下:
globallog127.0.0.1local2 chroot/var/lib/haproxy pidfile/var/run/haproxy.pid maxconn4000user haproxy group haproxy daemon defaults mode http logglobaloption httplog option dontlognull option http-server-close option forwardforexcept 127.0.0.0/8option redispatch retries3timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn3000frontend webserver/*:80 /#监听80,也可以使用bind定义,类似于nginx中的server default_backend web /#指明代理的后端服务器为web backend web/#定义web包含的服务器详细以及使用的算法,类似nginx中的upstream balance roundrobin server web110.1.210.52:80check server web210.1.210.53:80 check
说明:在以上配置中frontend段定义了前台代理配置,代理的后端服务器由default_backend指定,web则是代理的真实后端服务器名称,而web的定义由backend 字段负责。
chroot: /#修改haproxy的工作目录至指定的目录,并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是确保指定的目录为空目录且任何用户均不能有写权限; daemon: /#让haproxy以守护进程的方式工作于后台,其等同于"-D"选项的功能,当然,也可以在命令行中以"-db"选项将其禁用; gid: /#以指定的GID运行haproxy,建议使用专用于运行haproxy的GID,以避免因权限带来的风险; group: /#同gid,不过这里为指定的组名; uid: /#已指定的UID身份运行haproxy进程; user: /#同uid,但这里使用的为用户名; log: /#定义全局的syslog服务器,最多可以定义两个; nbproc: /#指定启动的haproxy进程个数,只能用于守护进程模式的haproxy;默认为止启动一个进程,鉴于调试困难等多方面的原因,一般只在但进程仅能打开少数文件描述符的场中才使用多进程模式; pidfile: /#pid文件的存放位置; ulimit-n: /#设定每个进程所能够打开的最大文件描述符,默认情况下其会自动进行计算,因此不建议修改此选项; node: /#定义当前节点的名称,用于HA场景中多haproxy进程共享同一个IP地址时; description: /#当前实例的描述信息; maxconn: /#设定每个haproxy进程所接受的最大并发连接数,其等同于命令行选项"-n","ulimit-n"自动计算的结果正式参照从参数设定的; maxpipes: /#haproxy使用pipe完成基于内核的tcp报文重组,此选项用于设定每进程所允许使用的最大pipe个数,每个pipe会打开两个文件描述符,因此,"ulimit -n"自动计算的结果会根据需要调大此值,默认为maxcoon/4; noepoll: /#在linux系统上禁用epoll机制; nokqueue: /#在BSE系统上禁用kqueue机制; nopoll: /#禁用poll机制; nosepoll: /#在linux系统上禁用启发式epoll机制; nosplice: /#禁止在linux套接字上使用tcp重组,这会导致更多的recv/send调用,不过,在linux2.6.25-28系列的内核上,tcp重组功能有bug存在; spread-checks<0..50,in percent>: /#在haprorxy后端有着众多服务器的场景中,在紧缺是时间间隔后统一对中服务器进行健康状况检查可能会带来意外问题,此选项用于将检查的时间间隔长度上增加或减少一定的随机时长,为当前检查检测时间的%; maxconnrate:/#设置每个进程每秒种所能建立的最大连接数量,速率,一个连接里可以有多个会话,也可以没有会话 maxsessrate:/#设置每个进程每秒种所能建立的最大会话数量 maxsslconn:/#每进程支持SSL 的最大连接数量 tune.bufsize: /#设定buffer的大小,同样的内存条件下,较小的值可以让haproxy有能力接受更多的并发连接,较大的值了可以让某些应用程序使用较大的cookie信息,强烈建议使用默认值; tune.chksize: /#设定检查缓冲区的大小,单位为字节,更大的值有助于在较大的页面中完成基于字符串或模式的文本查找,但也会占用更多的系统资源,不建议修改; tune.maxaccept: /#设定haproxy进程内核调度运行时一次性可以接受的连接的个数,较大的值可以带来较大的吞吐量。 tune.maxpollevents: /#设定一次系统调用可以处理的事件最大数,默认值取决于OS,其至小于200时可介于带宽,但会略微增大网络延迟,但大于200时会降低延迟,但会稍稍增加网络带宽的占用; tune.maxrewrite: /#设定在首部重写或追加而预留的缓存空间,建议使用1024左右的大小,在需要更大的空间时,haproxy会自动增加其值; tune.rcvbuf.client: /#设定内核套接字中客户端接收缓存区的大小,单位为字节,强烈推荐使用默认值; tune.rcvbuf.server: /#设定内核套接字中服务器接收缓存区的大小,单位为字节,强烈推荐使用默认值; tune.sndbuf.client: /#设定内核套接字中客户端发送缓存区的大小,单位为字节,强烈推荐使用默认值; tune.sndbuf.server: /#设定内核套接字中服务器端发送缓存区的大小,单位为字节,强烈推荐使用默认值; debug: /#调试模式,输出启动信息到标准输出; quiet: /#安装模式,启动时无输出;
defaults mode http/#默认负载均衡模式为http log global /#日志定义 option httplog /#启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求 option dontlognull /#设置日志中不记录空连接。 option httpclose /#每次请求完毕后主动关闭http通道 option forwardfor except 127.0.0.0/8 /#插入x-forward标记,反向代理时候可以通过该字段获取客户端真实IP retries 3 /#定义连接后端服务器的失败重连次数 timeout http-request 10s:/#在客户端建立连接但不请求数据时,关闭客户端连接 timeout queue 1m : /#服务器的maxconn时,连接在队列中保持挂起状态而设置的超时时间,想客户端返回503错误 timeout connect 10s: /#定义haproxy将客户端请求转发至后端服务器所等待的超时时长 timeout client 1m:/#客户端非活动状态的超时时长 timeout server 1m:/#客户端与服务器端建立连接后,等待服务器端的超时时长 timeout http-keep-alive 10s: /#定义保持连接的超时时长 timeout check 10s: /#健康状态监测时的超时时间,过短会误判,过长资源消耗 maxconn 3000: /#每个server最大的连接数
timeout http request :/#在客户端建立连接但不请求数据时,关闭客户端连接 timeout queue :/#等待最大时长 timeout connect: /#定义haproxy将客户端请求转发至后端服务器所等待的超时时长 timeout client:/#客户端非活动状态的超时时长 timeout server:/#客户端与服务器端建立连接后,等待服务器端的超时时长, timeout http-keep-alive :/#定义保持连接的超时时长 timeout check:/#健康状态监测时的超时时间,过短会误判,过长资源消耗
bind [
]:示例:listen httpproxy bind :80,:443bind10.0.0.1:10080,10.0.0.1:10443bind/var/run/ssl-frontend.sock user root mode 600 accept-proxy listen httphttpsproxy bind :80bind :443 ssl crt /etc/haproxy/site.pem listen httphttpsproxyexplicit bind ipv6@:80bind ipv4@publicssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen externalbindapp1 bind fd@${FDAPP1}
balance
algorithm有如下几种算法:
mode { tcp|http|health }/#指定代理模式
hash-type
log globallog
示例:[root@app51 ~]/#vi /etc/haproxy/haproxy.cfg log 127.0.0.1local2 [root@app51~]/#systemctl restart haproxy [root@app51 ~]/#vi /etc/rsyslog.conf /#/#/#haproxy $ModLoad imudp $UDPServerRun514local2./* /var/log/haproxy.log [root@app51~]/#systemctl restart rsyslog
capture request header
示例:capture response header Content-length len 9capture response header Location len15capture request header Host len15capture request header X-Forwarded-For len 15capture request header Referer len15
usebackend
示例:
usebackend dynamic ifurldyn usebackend staticifurlcss urlimg extensionimg default_backend dynamic
server
示例:server first 10.1.1.1:1080 cookie first check inter 1000server second10.1.1.2:1080 cookie second check inter 1000server transp ipv4@ server backup ${SRVBACKUP}:1080backup server www1dc1 ${LANDC1}.101:80server www1dc2 ${LAN_DC2}.101:80
option httpchk option httpchk
示例:option httpchk GET /index.html
option forwardfor [ except
需要注意的是,HAProxy工作于隧道模式,其仅检查每一个连接的第一个请求,因此,仅第一个请求报文被附加此首部。如果想为每一个请求都附加此首部,请确保同时使用了option httpclose、option forceclose和option http-server-close几个option。示例:
frontend www mode http option forwardforexcept 127.0.0.1
option httplog [ clf ]/#启用记录HTTP请求、会话状态和计时器的功能,认情况下,日志输入格式非常简陋,因为其仅包括源地址、目标地址和实例名称/#而“option httplog”参数将会使得日志格式变得丰富许多,其通常包括但不限于HTTP请求、连接计时器、会话状态、连接数、捕获的首部及cookie、“frontend”、“backend”及服务器名称,当然也包括源地址和端口号等。
errorfile
:指定对HTTP的哪些状态码返回指定的页面;这里可用的状态码有400、403、408、500、502、503和504;
示例:errorfile 400 /etc/haproxy/errorfiles/400badreq.http errorfile408 /dev/null /#workaround Chrome pre-connect bug errorfile 403 /etc/haproxy/errorfiles/403forbid.http errorfile503 /etc/haproxy/errorfiles/503sorry.http
errorloc
:指定对HTTP的哪些状态码返回指定的页面;这里可用的状态码有200、400、403、408、500、502、503和504;
reqadd
示例:
/#Add "X-Proto: SSL" to requests coming via port 81 acl is-ssl dst_port 81reqadd X-Proto: SSL if is-ssl/#remove X-Forwarded-For header and SERVER cookie reqidel ^X-Forwarded-For:./*reqidel^Cookie:./*SERVER=
附上:官方1.5使用手册
ACL(Access Control List),即访问控制列表,HAProxy的ACL提供了一种灵活的解决方案来执行内容切换,并且通常基于从请求,响应或任何环境状态中提取的内容来做出决策。控制列表原则很简单:
需要提醒的是,获取的样本数据不光可以使用在acl中,也可以使用别处,例如记录log中。
定义ACL语法:acl
[flags]:标志,用于对
-i : /#忽略大小写 -f filename : /#从文件中载入模式 -m method : /#指定模式匹配方法 -n : /#禁止DNS解析 -M : /#-f 载入的文件作为映射文件使用 -u : /#强制ACL的名称唯一 -- : /#强制结束flag结束,避免了字符串中含有的- 引起混淆 其中flag中的 -m 选项可使用的模式匹配方法如下,需要说明的是有些方法已被默认指定无需声明,例如int,ip:"found" : /#只是用来探测数据流中是否存在指定数据,不进行任何比较 "bool" : /#检查结果返回布尔值。匹配没有模式,可以匹配布尔值或整数,不匹配0和false,其他值可以匹配 "int" : /#匹配整数类型数据;可以处理整数和布尔值类型样本,0代表false,1代表true "ip" : /#匹配IPv4,IPv6地址类型数据。该模式仅被IP地址兼容,不需要特别指定 "bin" : /#匹配二进制数据 "len" : /#匹配样本的长度的整数值 "str" : /#精确匹配,根据字符串匹配文本 "sub" : /#子串匹配,匹配文本是否包含子串 "reg" : /#正则匹配,根据正则表达式列表匹配文本 "beg" : /#前缀匹配,检查文本是否以指定字符串开头 "end" : /#后缀匹配,检查文本是否以指定字符串结尾 "dir" : /#子目录匹配,检查部分文本中以" / "作为分隔符的内容是否含有指定字符串 "dom" : /#域匹配。检查部分文本中以" . "作为分隔符的内容是否含有指定字符串
[operator]:操作符,通常分字符串和整数,如下
/#/#/#匹配整数值: eq /#等于 ge /#大于等于 gt /#大于 le /#小于 lt /#小于等于/#/#/#匹配字符串: exact match /#精确匹配 substring match /#子串匹配 prefix match /#前缀匹配 suffix match /#后缀匹配 subdir match /#子路径匹配 domain match /#子域名匹配[operator]
[
boolean /#布尔型 integer or integer range /#整数或整数范围 IP address / network /#IP或网络地址 string /#字符串 hex block /#16进制的块匹配value类型
在使用多个ACL作为条件可使用逻辑运算符:
四层访问控制一般只能针对IP以及端口来进行,其指定是 tcp-request。
语法:tcp-request connection
示例:/#阻断来自非10.1.210.52访问80端口的请求 frontend webserver acl myhost src10.1.210.52acl myport dstport80tcp-request connection reject if!myhost myport bind0.0.0.0:80defaultbackend app
七层上的访问控制方法有多种,列如可以利用http的报文、头信息、URL、PATH等相关信息进行访问控制,访问控制的指令也有多个,常用指令如下:/#阻断符合ACL的访问请求 block { if | unless }
在以上控制指令中,block语法可以使用http-request deny代替。
示例一:根据条件制定后端服务器/#请求资源为图片,则调用图片服务器后端 acl picture pathend -i .jpg .png .gif usebackend server_imgif picture
示例二:阻断请求
/#根据http头信息中的User-Agent阻断火狐浏览器访问 frontend webserver bind0.0.0.0:80acl badcurl hdrsub(User-Agent) -i ./firefox./ /#hdrsub根据头信息中的字符串匹配 block ifbadcurl default_backend app
示例三:允许或拒绝http请求
/#拒绝POST HEAD 方式之外的HTTP请求 acl validmethod method POST HEAD http-request deny if ! validmethod
除了以上控制指令还有比如内部状态控制指令,如会话速率:/#与后端建立会话速率,每秒钟建立的新会话 besessrate([
示例一:
/#某后端被请求速率大于100,则重定向至错误页,可以用于阻止一些攻击行为 mode http acl beingscanned besessrate gt100redirect location/denied.html if beingscanned
示例二:
/#限定入站邮件速率不能大于50封/秒,所有在此指定范围之外的请求都将被延时50毫秒 frontend mail bind :25mode tcp maxconn500acl toofast fesessrate ge50tcp-request inspect-delay 50ms tcp-request content accept if! toofast tcp-request content accept if WAIT_END
HAProxy优点之一就是自带状态监控页面,开启监控页面需要配置stats enable。
开启statslisten admin bind/*:5656 /#定义监听端口 stats enable /#启用状态统计报告 stats auth admin:admin /#设置统计页面用户名和密码设置 stats uri /admin /#定义统计页面的URL,默认为/haproxy?stats stats hide-version /#隐藏统计页面上HAProxy的版本信息 stats refresh 30s /#统计页面自动刷新时间 stats admin if TRUE /#如果认证通过就做管理功能,可以管理后端的服务器 stats realm “LOGIN” /#登陆页面提示信息
访问:http://ip:5656/admin登陆后即可看到管理页面。
frontend web /:80bind/:443 ssl crt /etc/haproxy/haproxy.crt /#haproxy.crt包含key和pem秘钥对 reqadd X-Forwarded-Proto: https /#头信息中添加https协议 redirect scheme https if !{ sslfc } /#将80端口跳转到443 defaultbackend webserver backend webserver balance roundrobin server app110.1.210.52:80check server app210.1.210.53:80 check
listen mysql_36 0.0.0.0:3306mode tcp option tcplog balance leastconn option tcpka option mysql-check user haproxy server10.1.210.52 10.1.210.53:3306 weight 1 check inter 1s rise 2 fall 2
frontend webservs bind/*:80acl url_static path_beg-i /static /images /javascript /stylesheets acl url_static path_end-i .jpg .gif .png .css .js .html acl url_php path_end-i .php acl host_static hdr_beg(host)-i img. imgs. video. videos. ftp. image. download. use_backend staticif url_static orhost_static use_backend dynamicifurl_php default_backend dynamic backend static balance roundrobin server node110.1.210.52:80 check maxconn 1000backend dynamic balance roundrobin server node210.1.210.53:80 check maxconn 1000