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
配置文件结构
global settings:#全局参数配置,主要用于定义haproxy进程管理安全及性能相关的参数 defaults <name>:#默认配置参数,下面的段继承该配置,名称是可选的,这配置默认配置参数可由下一个"defaults"所重新设定 frontend <name>:#前端配置,定义一系列监听的套接字,这些套接字可接受客户端请求并与之建立连接,可以监听多个端口。 backend <name>:#后端配置,定义后台服务器,前端代理服务器将会把客户端的请求调度至这些服务器,类似nginx中的upstream listen <name>:#定义一组前端和后端的完整代理,可理解为frontend+backend,通常用于tcp流量代理
#ps:name名称必须由大写和小写字母,数字,‘-‘,‘_‘,‘.‘组成
配置参数可支持的时间单位
- us : 微秒. 1 microsecond = 1/1000000 s - ms : 毫秒. 1 millisecond = 1/1000 s - s : 秒 1s = 1000ms - m : 分 1m = 60s = 60000ms - h : 小时 1h = 60m = 3600s = 3600000ms - d : 天 1d = 24h = 1440m = 86400s = 86400000ms
一个超级简单的WEB配置示例如下:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon 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 webserver *:80 #监听80,也可以使用bind定义,类似于nginx中的server default_backend web #指明代理的后端服务器为web backend web #定义web包含的服务器详细以及使用的算法,类似nginx中的upstream balance roundrobin server web1 10.1.210.52:80 check server web2 10.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 [<address>]:<port_range> [,...] [param*] #此指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字
示例:
listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind fd@${FD_APP1}
balance <algorithm> [ <arguments> ] balance url_param <param> [check_post] #定义负载均衡算法,可用于defaults、listen和backend段。
mode { tcp|http|health } #指定代理模式
hash-type <method> <function> <modifier> #用于将hash码映射至后端服务器的方法;可用方法有map-based和consistent,一般情况推荐使用默认的map-based方法。
log global log <address> <facility> [<level> [<minlevel>]] #用于日志配置,可以用于所有的配置段,每个段中最多可以指定两个log参数,如果使用了“log global”且”global”段已经定了两个log参数时,多余了log参数将被忽略
示例:
[root@app51 ~]# vi /etc/haproxy/haproxy.cfg log 127.0.0.1 local2 [root@app51 ~]# systemctl restart haproxy [root@app51 ~]# vi /etc/rsyslog.conf ###haproxy $ModLoad imudp $UDPServerRun 514 local2.* /var/log/haproxy.log [root@app51 ~]# systemctl restart rsyslog
capture request header <name> len <length> capture response header <name> len <length> #用于捕获并记录最近一次出现的指定请求首部或响应首部。请求首部是从客户端发起的请求首部,响应首部是从后端server响应并在haproxy准备发送给客户端前捕获的。 #捕获的首部值使用大括号{}括起来后会添加进日志中。如果需要捕获多个首部值,它们将以指定的秩序出现在日志文件中,并以竖线"|"作为分隔符。不存在的首部记录为空字符串.定义在frontend和listen段
示例:
capture response header Content-length len 9 capture response header Location len 15 capture request header Host len 15 capture request header X-Forwarded-For len 15 capture request header Referer len 15
use_backend <backend> [{if | unless} <condition>] #用于定义满足条件的backend,条件判断是可选的,并且condition是基于acl的条件。 default_backend <backend> #用于指定默认的backend,在没有匹配的”use_backend”规则时为实例指定使用的默认后端。
示例:
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
server <name> <address>[:port] [param*] #为后端声明一个server,因此,不能用于defaults和frontend区段。
示例:
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup ${SRV_BACKUP}:1080 backup server www1_dc1 ${LAN_DC1}.101:80 server www1_dc2 ${LAN_DC2}.101:80
option httpchk option httpchk <uri> option httpchk <method> <uri> option httpchk <method> <uri> <version> #此指令表示基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康。不设置该选项时,默认采用tcp做健康检查,只要能建立tcp就表示健康
示例:
option httpchk GET /index.html
option forwardfor [ except <network> ] [ header <name> ] [ if-none ] #允许在发往服务器的请求首部中插入“X-Forwarded-For”首部。
frontend www mode http option forwardfor except 127.0.0.1
option httplog [ clf ] #启用记录HTTP请求、会话状态和计时器的功能,认情况下,日志输入格式非常简陋,因为其仅包括源地址、目标地址和实例名称 #而“option httplog”参数将会使得日志格式变得丰富许多,其通常包括但不限于HTTP请求、连接计时器、会话状态、连接数、捕获的首部及cookie、“frontend”、“backend”及服务器名称,当然也包括源地址和端口号等。
errorfile <code> <file> #错误页面配置,常用错误如404、403、400、500等
示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http errorfile 408 /dev/null # workaround Chrome pre-connect bug errorfile 403 /etc/haproxy/errorfiles/403forbid.http errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorloc <code> <url> errorloc302 <code> <url> #请求错误时,返回一个HTTP重定向至某URL的信息;可用于所有配置段中。
reqadd <string> [{if | unless} <cond>] #在HTTP请求的末尾添加标头 rspadd <string> [{if | unless} <cond>] #在HTTP响应的末尾添加标头 reqdel <search> [{if | unless} <cond>] #删除与HTTP请求中的正则表达式匹配的所有头信息 rspdel <search> [{if | unless} <cond>] #删除与HTTP响应中的正则表达式匹配的所有头信息 reqidel <search> [{if | unless} <cond>] #忽略大小写删除同reqdel rspidel <search> [{if | unless} <cond>] #忽略大小写删除同rspidel
示例:
#Add "X-Proto: SSL" to requests coming via port 81 acl is-ssl dst_port 81 reqadd 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 <aclname> <criterion> [flags] [operator] [<value>] ...
###基于tcp的criterion##### dst : #目标ip dst_port : #目标端口 src : #源ip src_port : #源端口 ###基于http的criterion##### ###url_path相关 #ps: path从第一个"/"开始,不包含host,不包含参数 path : #精确匹配 path_beg : #前缀匹配 path_dir : #子串匹配 path_dom : #子域名匹配 path_end : #路径后缀匹配 path_len : #路径长度匹配 path_reg : #路径的正则表达式模式匹配 path_sub : #路径的子字串匹配 ###url相关 #ps:url包含了包含host和path以及参数 url : #精确匹配 url_beg : #前缀匹配 url_dir : #子串匹配 url_dom : #子域名匹配 url_end : #后缀匹配 url_len : #长度匹配 url_reg : #正则表达式匹配 url_sub : #子字串匹配 ###http头信息相关 hdr([<name>[,<occ>]]) : #精确匹配 hdr_beg([<name>[,<occ>]]) : #前缀匹配 hdr_dir([<name>[,<occ>]]) : #子串匹配 hdr_dom([<name>[,<occ>]]) : #子域名匹配 hdr_end([<name>[,<occ>]]) : #后缀匹配 hdr_len([<name>[,<occ>]]) : #长度匹配 hdr_reg([<name>[,<occ>]]) : #正则表达式匹配 hdr_sub([<name>[,<occ>]]) : #子字串匹配 ###http请求方法 method [string] :#匹配http请求方法,string为http方法
[flags]:标志,用于对<criterion>进行局部调整,一下为可使用的列表:
-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 #子域名匹配
[<value>]:值,操作符右边的值,通常为以下几种类型:
boolean #布尔型 integer or integer range #整数或整数范围 IP address / network #IP或网络地址 string #字符串 hex block #16进制的块匹配
在使用多个ACL作为条件可使用逻辑运算符:
四层访问控制一般只能针对IP以及端口来进行,其指定是 tcp-request。
语法:
tcp-request connection <action> [{if | unless} <condition>]
示例:
#阻断来自非10.1.210.52访问80端口的请求 frontend webserver acl myhost src 10.1.210.52 acl myport dst_port 80 tcp-request connection reject if !myhost myport bind 0.0.0.0:80 default_backend app
七层上的访问控制方法有多种,列如可以利用http的报文、头信息、URL、PATH等相关信息进行访问控制,访问控制的指令也有多个,常用指令如下:
#阻断符合ACL的访问请求 block { if | unless } <condition> #允许或拒绝http请求的控制指令 http-request { allow | deny} [ { if | unless } <condition> ] #根据条件来调用指定后端 use_backend <backend> [{if | unless} <condition>]
#请求资源为图片,则调用图片服务器后端 acl picture path_end -i .jpg .png .gif use_backend server_img if picture
示例二:阻断请求
#根据http头信息中的User-Agent阻断火狐浏览器访问 frontend webserver bind 0.0.0.0:80 acl bad_curl hdr_sub(User-Agent) -i .*firefox.* #hdr_sub根据头信息中的字符串匹配 block if bad_curl default_backend app
示例三:允许或拒绝http请求
#拒绝POST HEAD 方式之外的HTTP请求 acl valid_method method POST HEAD http-request deny if ! valid_method
除了以上控制指令还有比如内部状态控制指令,如会话速率:
# 与后端建立会话速率,每秒钟建立的新会话 be_sess_rate([<backend>]) : integer #与前端代理会话建立速率,每秒钟建立的新会话 fe_sess_rate([frontend]) <integer>
示例一:
# 某后端被请求速率大于100,则重定向至错误页,可以用于阻止一些攻击行为 mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
示例二:
#限定入站邮件速率不能大于50封/秒,所有在此指定范围之外的请求都将被延时50毫秒 frontend mail bind :25 mode tcp maxconn 500 acl too_fast fe_sess_rate ge 50 tcp-request inspect-delay 50ms tcp-request content accept if ! too_fast tcp-request content accept if WAIT_END
HAProxy优点之一就是自带状态监控页面,开启监控页面需要配置stats enable。
开启stats
listen 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 *:80 bind *:443 ssl crt /etc/haproxy/haproxy.crt #haproxy.crt包含key和pem秘钥对 reqadd X-Forwarded-Proto:\ https #头信息中添加https协议 redirect scheme https if !{ ssl_fc } #将80端口跳转到443 default_backend webserver backend webserver balance roundrobin server app1 10.1.210.52:80 check server app2 10.1.210.53:80 check
listen mysql_36 0.0.0.0:3306 mode tcp option tcplog balance leastconn option tcpka option mysql-check user haproxy server 10.1.210.52 10.1.210.53:3306 weight 1 check inter 1s rise 2 fall 2
frontend webservs bind *:80 acl 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 static if url_static or host_static use_backend dynamic if url_php default_backend dynamic backend static balance roundrobin server node1 10.1.210.52:80 check maxconn 1000 backend dynamic balance roundrobin server node2 10.1.210.53:80 check maxconn 1000
原文:https://www.cnblogs.com/navysummer/p/10518078.html