Haproxy
HAproxy
代理作用:web缓存(加速)、反向代理、内容路由(根据流量及内容类型将请求转发至特定服务器)、转码器:compress
缓存作用:减少冗余内容传输,节省带宽,缓解网络瓶颈、降低了对原始服务器的压力,降低了请求延迟
HAproxy:只是一个HTTP协议的反向代理,不提供缓存功能,但额外支持对基于TCP通信的应用做LB
套接字限制HAproxy的并发能力,linux最大端口范围0-65535,HAproxy需要和前段用户和后端服务器建立连接,每一个连接就是一个套接字,可以通过缓存减少和后端服务器的连接,通过调大端口范围,提高HAproxy的并发能力,提高文件打开数量限制
安装
yum -y install haproxy
安装完成后的主要文件
[root@localhost ~]# rpm -ql haproxy
/etc/haproxy
/etc/haproxy/haproxy.cfg #主配置文件
/etc/logrotate.d/haproxy
/etc/sysconfig/haproxy
/usr/bin/halog
/usr/bin/iprange
/usr/lib/systemd/system/haproxy.service
/usr/sbin/haproxy
/usr/sbin/haproxy-systemd-wrapper
配置日志文件
在/etc/rsyslog.conf 中打开下面两行的注释,打开rsyslog服务在UDP 514端口的监听
$ModLoad imudp
$UDPServerRun 514
添加下面的这一行添加日志
local2.* /var/log/haproxy.log
然后启动日志服务
systemctl start rsyslog
代理参数:
-
balance:指明负载均衡的调度算法
- 动态: 权重可动态调整
- 静态: 调整权重不会实时生效
- roundrobin: 轮询,动态算法,每个后端主机最多只能支持4128个连接;
- static-rr: 轮询,静态算法,每个后端主机支持的数量无上限;
- leastconn:最少连接算法,根据后端主机的负载数量进行调度,动态算法,仅适用于长连接的会话;
- source: 将连接请求的源地址进行hash运算,并 同一IP始终发送给同一个服务器。
- hash-type:
- map-based: 取模法:静态
- consistent:一执行hash法:动态
- hash-type:
- uri:
- 根据Url前半部分hash计算出转发后端服务器,统一url都是转发到同一服务器
- map-based
- consistent
- url_param:根据url中的指定额值进行调度,并把值做hash运算,并除以总权重;动静取决于hash算法
- hash-type:
- map-based
- consistent
- hdr(
):根据请求报文中指定的header(user-agent,refer,hostname)进行调度;把指定的header的值进行hash计算;
-
bind :只能用于frontend,listen
-
bind [
]:<port_range> [, ….] interface-
address: 可选项,其可以为主机名、ipv4地址、ipv6地址或*:省略此选项,将其指定为 * 或0.0.0.0时,将监听系统的所有ipv4地址
-
port_range:可以是一个特定的TCP端口,也可以是一个端口范围,如5005-5010,代理服务器通过指定的端口来接收客户端的请求:需要注意的是,每组监听的套接字address:port
在同一个实例上只能使用一次,而且小于1024端口需要有特定权限的用户才能使用,这可能需要通过uid参数来定义
-
interface:指定物理接口的名称,仅能在linux系统上使用:其不能使用接口别名。而仅能使用物理接口名称,而且只有管理有权限指定绑定的物理接口。
-
-
-
mode:(tcp|http|health)
-
设定实例运行的模式或协议,当实现内容交换时,前段和后端必须工作于同一种模式(一般来说都是http模式),否则将无法启动实例。
-
tcp:实例运行于纯tcp模式,在客户端和服务器端之间将建立一个全双工的连接。且不会对7层报文做任何类型的检查:此为默认模式,通常用于SSL,SSH,SMTP等应用
-
http:实例运行于HTTP模式,客户端请求在转发至后端服务器之前将被深度分析,所有不与RFC格式兼容的请求都会被拒绝
-
health:实例工作于health模式,其对入站请求仅响应“ok”信息并关闭连接,且不会记录任何日志信息:此模式将用于响应外部组件的健康状态检查请求:目前来讲此模式已经废弃,因为
tcp或http模式中的monitor关键字可完成类似功能
-
-
hash-type
定义用于将hash码映射至后端服务器的方法:其不能用于frontend区段:可用方法有map-bashd和consistent
-
log
log global
log
[ [ ] ]
为 每个实例启用时间和流量日志,因此可用于所有区段,每个实例最多可以指定两个log参数,不过使用log global 且global 段已经定了两个log参数时,多余的log参数将被忽略
address: 定义日志发往的位置,其格式之一可以为IPv4_address:PORT,其中的PORT为UDPO协议的端口,默认为514,格式二可以为Unix套接字文件路径,但需要留心chroot应
用及用户的读写权限; facility:可以为syslog系统的标准facility之一,level: 第一日志级别,即输出信息过滤器 ,默认为所有信息:指定级别时,所有等于或高于此级别的日志信息将会被发送
-
maxconn:设定最大并发连接数,不能用于backend,此最大值不能超过global中定义的连接数,haproxy为每个连接维持两个缓冲,每个缓冲的大小为8kb,再加上其他的数据,每个连接将大约占用17KB的RAM空间,这意味着经过适当优化后,理论上有着1GB的可用RAM空间时HAproxy将能维护40000到50000并发连接
-
default_backend:为frontend指明使用的默认后端
-
server
-
server
[:port][ param*] -
name:为此服务器指定的内部名称,其将出现在日志及警告信息中:如果设定了“http-send-server-name”,它还将被添加至发往此服务器的请求首部中
-
address:此服务器的ipv4地址,也支持使用可解析的主机名,只不过在启动时需要解析主机名至相应的IPV4地址
-
port 可选项,未设定时,将使用客户端请求时的同一端口
-
param:为此服务器设定的一系列参数
-
backup 设定为备用服务器,仅在负载均衡场景中的其它server均不可用时,启用此server
-
check: 启用对此server执行状态健康检查,其可用于额外的其它参数完成更精细的设定,如:
- inter
:设定健康检查的时间间隔,单位为毫秒,默认为2000:也可以使用fastinter和downinter来根据服务器端状态优化此事件延迟 - rise
:设定健康检查中,某离线的server从离线状态转换至正常状态需要成功检查的次数 - fall
: 确认server从正常状态转换为不可用状态需要检查的次数
- inter
-
cookie
: 为指定server设定cookie值,此处指定的值将在请求入站时被检查,第一次此值挑选的server将在后续的请求中被选中,其目的在于实现持久化的连接的功能 -
maxconn
: 指定服务器接受的最大并发连接数:如果发往此服务器的连接数目高于此处指定的值,其将被放置在请求队列,以等待其他连接被释放,maxqueue :设定请求队列的最大长度 -
observe
:通过观察服务器的通信状况来判定其健康状态,默认为禁用 -
redir
:启用重定向功能,将发往此服务器的GET和HEAD请求均以302状态码响应:需要注意的是,在prefix后面不能使用/,且不能使用相对地址,以免造成死循环:例如: server srv1 172.16.100.6:80 redir http://imageserver.linux.com check
weight
:权重,默认为1,最大值为256,0表示不参与负载均衡
-
-
-
capture request header
len :向日志中记录额外信息 捕获并记录请求首部最近一次出现时的第一个值,仅能用于“frontend”和“listen”字段。捕获的首部值使用花括号{}括起来后添加进日志中。如果需要捕获多个首部值,它们将以指定的次序出现在日志文件中,并以“|”作为分隔符。不存在的首部记录为空字符串,最长需要捕获的首部包括在虚拟主机环境中使用“HOST”、上传请求中的“Content-length”、快速区别真实用户和网络机器人的“User-agent”,以及代理环境中记录真实请求来源的“X-Forward-For”
name:要捕获的首部名称
length:要记录的首部长度,超出部分将被忽略
-
option httplog [clf]: 启用记录HTTP请求、会话状态和计时器的功能
当mode为http时,记录丰富的日志信息
-
option logasap
option no logasap 启用或禁用提前将HTTP请求记录日志,不能用于backend区段
默认情况下,HTTP请求是在请求结束时进行记录以便能将其整体传输时长和字节数计入日志,由此,传较大的对象时,其记录日志的时长可能会略有延迟,option logasap参数能够在服务器发送
complete首部时即时记录日志,只不过,此时将不记录整体传输时长和字节数,从情形下,捕获“Content-Length”响应首部来记录传输的字节数是一个较好的选择。下面是一个例子:
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 172.16.100.9 local2
-
option forwardfor
option forwardfor [except
][head ] [if-none] 允许在发往服务器的请求首部中插入“X-Forwarded-For”首部
network:可选参数,当指定时,源地址为匹配至此网络中的请求都禁用此功能
name:可选参数,可使用一个自定义的首部,如“X-Client”来代替“X-Forwarded-For”,有些独特的web服务器的确需要一个独特的首部。
if-none:仅在此首部不存在时才将其添加至请求报文当中
HAproxy工作于反向代理模式,其发往服务器的请求中的客户端IP均为HAproxy主机的地址而非真正客户端的地址,这会使得服务器端的日志信息记录不了真实的请求来源,“X-Forwarded-For”首部则可用于解决此问题。HAProxy可以向每个发往服务器的请求上添加次首部,并以客户端IP为其value。
需要注意的是,HAProxy工作于隧道模式,其仅检查每一个连接的第一个请求,因此,仅第一个请求报文被附加此首部,如果想为每一个请求都附加此首部,请确保使用了“option httpclose、“option forceclose”和“option http-server-close” 几个option下面是一个例子:
frontend www mode http option forwardfor except 127.0.0.1
-
option http-server-close :在长连接开启的时候,允许服务器端强制断开连接
-
errorfile
在用户请求不存在的页面时,返回一个页面文件给客户端而非由haproxy生成的错误代码:可用于所有段中
code:指定对HTTP的哪些状态码返回指定的页面,这里可用的状态码有200、400、403、408、500、502、503和504;注意没有404,404是由后端服务器判断返回的
file: 用于指定用于响应的文件
例如: errorfile 400 /etc/haproxy/errorpages/400badreq.http
errorfile 403 /etc/haproxy/errorpages/403forbid.http
-
errorloc 和errorloc302
errorloc
errorloc302
请求错误时,返回一个HTTP重定向至某URL的信息:可用于所有配置段中
需要留意的是,这两个关键字都会返回302状态码,这将使得客户端使用同样的HTTP方法获取指定的URL,对于非GET方法的场景(如POST)来说会产生问题,因为返回客户的URL是不允许 使用GET以外的其它方法的,如果的确有这种问题,可以使用errorloc303来返回3030状态码给客户端
-
errorloc303
errorloc303
请求错误时,返回一个HTTP重定向至某URL的信息给客户端:可用于所有配置段中
backend webserver server 172.16.100.6 172.16.100.6:80 check maxconn 3000 cookie srv01 server 172.16.100.7 172.16.100.7:80 check maxconn 3000 cookie srv02 errorfile 403 /etc/haproxy/errorpages/sorry.htm errorfile 503 /etc/haproxy/errorpages/sorry2.htm
-
timeout http-request : 客户端请求报文请求超时时长
-
timeout connect tcp建立连接的超时时长
-
timeout client 当客户端不活动时的超时时间
-
timeout http-keep-alive keepalive 超时时间
自定义添加请求或响应报文首部
-
reqadd [{if | unless} ]
在请求首部末尾添加信息
-
repadd 在后端服务器返回首部信息中添加信息,例如:
frontend main *:80
default_backend websrvs
rspadd Via:\ node1.leo.com
访问控制:
haproxy的acl用于实现基于请求报文的首部、响应报文的内容或其它的环境状态信息来做出转发决策,这大大增强了其配置弹性。其配置法则通常分为两步,首先定义acl,即定义一个测试条件,而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。定义acl的语法格式如下:
acl [flags][operator] …
aclname: ACL名称,区分字符大小写
criterion: 测试标准,即对什么信息发起测试:测试方式可以由[flags]指定的标志进行调整:而有些测试标准也可以需要为其在value之前指定一个操作符operator
flags:目前haproxy的acl支持的标志位有3个:
- -i : 不区分value中模式字符的大小写
- -f:从指定的文件加载模式
- --:标志的强制结束标记,在模式中的字符串像标记符时使用
示例:
acl nagios src 192.168.129.3
acl local_net src 192.168.0.0/
acl auth_ok http_auth(L1)
http-request allow if nagios
http-request allow if local_net auth_ok
http-request auth realm Gimme if local_net auth_ok
http-request deny
常用测试标准
-
be_sess_rate
be_sess_rate(backend)
用于测试指定的backend上会话创建的速率(即每秒创建的会话数)
是否满足指定的条件:常用于在指定的backend上的会话速率过高时将用户请求转发至另外的backend,或用于阻止攻击行为。例如:
backend dynamic
mode http
acl being_scanned be_sess_rate gt 50
redirect location /error_pages/denied.html if being_scanned
-
fe_sess_rate
fe_sess_rate(frontend)
用于测试指定的frontend(或当前frontend)上的会话创建速率是否满足指定的条件:常用于为frontend指定一个合理的会话创建速率的上限以防止服务被滥用。例如下面的例子限定入站邮件的速率不能大于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
-
path_beg
用于测试请求的URL是否以string指定的模式开头。下面的例子用于测试URL是否以/static、/images、/javascript或/stylesheets开头
acl url_static path_beg -i /static /images /javascripts /stylesheets
-
path_end 是否以string指定的模式结尾
acl url_static path_end -i .jpg .gif .png .css .js
-
hdr_beg
用于测试请求报文的指定首部的开头是否符合string指定的模式
-
hdr_end 用于测试请求报文的指定首部的尾部是否符合string指定的模式
-
url_reg 匹配正则url
动静分离配置示例
frontend http-in
bind *:80
mode http
log global
option httpclose
option logasap
option dontlognull
capture request header Host len 20
capture request header Referer len 60
acl url_static path_beg -i /static /images /javascripts /stylesheets
acl url_dynamic path_end -i .jpg .gif .png .css .js
use_backend static_servers if url_static
default_backend dynamic_servers
backend static_servers
balance roundrobin
server imgsrv1 172.16.200.7:80 check maxconn 6000
server imgsrv2 172.16.200.8:80 check maxconn 6000
backend dynamic_servers
cookie srv insert nocache
balance roundrobin
server websrv1 172.16.200.7:80 check maxconn 1000 cookie websrv1
server websrv2 172.16.200.8:80 check maxconn 1000 cookie websrv2
server websrv3 172.16.200.9:80 check maxconn 1000 cookie websrv3
配置示例
默认配置如下:
global
log 127.0.0.1 local2 # 需要设置/etc/rsyslog.conf加上local2设备的日志记录级别和日志路径
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000 # 这是前端对外的最大连接数。代理http时,1G空闲内存承载20000以上没大问题
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats # 开启动态查看、管理haproxy的状态文件
# 另外建议设置spread-checks全局项,且百分比建议为2-5之间
defaults
mode http # 7层http代理,另有4层tcp代理
log global
option httplog # 在日志中记录http请求、session信息等
option dontlognull # 不要在日志中记录空连接
option http-server-close # 后端为动态应用程序建议使用http-server-close,后端为静态建议使用http-keep-alive
option forwardfor except 127.0.0.0/8 # haproxy将在发往后端的请求中加上"X-Forwarded-For"首部字段
option redispatch # 当某后端down掉使得haproxy无法转发携带cookie的请求到该后端时,将其转发到别的后端上
timeout http-request 10s # 此为等待客户端发送完整请求的最大时长,应该设置较短些防止洪水攻击,如设置为2-3秒
# haproxy总是要求一次请求或响应全部发送完成后才会处理、转发,
timeout queue 1m # 请求在队列中的最大时长,1分钟太长了。设置为10秒都有点长,10秒请求不到资源客户端会失去耐心
timeout connect 10s # haproxy和服务端建立连接的最大时长,设置为1秒就足够了。局域网内建立连接一般都是瞬间的
timeout client 1m # 和客户端保持空闲连接的超时时长,在高并发下可稍微短一点,可设置为10秒以尽快释放连接
timeout server 1m # 和服务端保持空闲连接的超时时长,局域网内建立连接很快,所以尽量设置短一些,特别是并发时,如设置为1-3秒
timeout http-keep-alive 10s # 和客户端保持长连接的最大时长。优先级高于timeout http-request高于timeout client
timeout check 10s # 和后端服务器成功建立连接后到最终完成检查的时长(不包括建立连接的时间,只是读取到检查结果的时长),
# 可设置短一点,如1-2秒
maxconn 3000 # 默认和前段的最大连接数,但不能超过global中的maxconn硬限制数
- 基于浏览器cookie实现session 绑定:
backend websrvs
balance roundrobin
cookie SERVERID insert nocache indirect
server web1 192.168.175.4:80 check weight 1 cookie websrv1
server web2 192.168.175.5:80 check weight 2 cookie websrv2
要点:
- 每个server有自己唯一的cookie标识
- 在backend中定义为用户请求调度完成后操纵其cookie
-
启用状态监控页
stats enable:启用基于程序编译时默认设置的统计报告,不能用于frontend区段。只要没有另外的其它设定,他们就会使用如下的配置:
- stats uri : /haproxy?stats
- stats realm : "HAProxy Statistics"
- stats auth : no authentication
- stats scope : no restriction
尽管stats enable 一条就能启用统计报告,但是还是建议设定其它所有的参数,以免其依赖于默认设定而带来的非期结果,下面是一个配置示例。
启用stats:
listen stats
bind *:9090 #绑定的端口
stats enable
stats hide-version #隐藏版本号
#stats scope . #加上这一行只显示一行
stats uri /haproxyadmin?stats #访问的路径 ip/haproxyadmin?stats
stats realm "Haproxy\ Stats" #认证提示信息
stats auth statsadmin:password #访问的账号密码
stats auth statsadmin2:password #可以设置多个账号密码
stats admin if TRUE #加上这一行可以启用web界面管理功能,可以在web几面直接操作服务启停,所以比较危险,建议不要开启
#注意绑定端口的时候需要关闭selinux 不然可能会报错
haproxy命令
haproxy -c -f /etc/haproxy/haproxy.cfg # 检查配置文件语法正确与否
systemctl start haproxy
systemctl reload haproxy
systemctl restart haproxy
systemctl stop haproxy