HAproxy简单概述
HAProxy是免费极速且可靠的用于为TCP和基于HTTP应用程序提供代理服务的解决方案。是工作在应用空间的程序,跟Nginx一样受限于套接字。且只类同于Nginx四层和七层代理服务器仅此而已。但更多用在web反向代理上!!!
HAProxy还可以将后端的服务器与网络隔离,起到保护后端服务器的作用。HAProxy的负载均衡能力虽不如LVS,但也是相当不错。而且由于其工作在7层,可以对http请求报文做深入分析,按照自己的需要将报文转发至后端不同的服务器(例如动静分离),这一点工作在4层的LVS无法完成。
其中一点点不同Nginx的是一个Master Worker模型负责接收用户请求,装载配置文件,平滑升级…但是更多的用户请求是通过worker来实现。而HAProxy是单一进程模型,支持多进程,但更多建议使用单一进程模型。使用单个进程直接响应用户多个请求,不启用子进程。也能够支持单进程巨大并发连接数,且必须支持事件驱动,如果不支持事件驱动,并发效率是可想而知。
HAproxy工作模式
HAProxy的工作模式一般有两种:
tcp模式:实例运行于TCP模式,在客户端和服务器端之间将建立一个全双工的连接,且不会对7层报文做任何类型的检查,只能以简单模式工作。此为默认模式,通常用于SSL、SSH、SMTP等应用。
http模式:实例运行于HTTP模式,客户端请求在转发至后端服务器之前将被深度分析,所有不与RFC格式兼容的请求都会被拒绝。
注意:当实现内容交换时,前端和后端必须工作于同一种模式(一般都是HTTP模式),否则将无法启动实例。
工作模式可通过mode参数在default,frontend,listen,backend中实现定义。
两种模块分别是:通过mod_tcp来限定反代模式和mod_http来实现负载均衡
帮助文档地址:http://cbonte.github.io/haproxy-dconv/,其它的地址就别想了
HAproxy演示环境
实验平台:Windows10_64
虚拟环境:基于Win系统搭建的VMware虚拟主机实现
所需要的虚拟主机:三台,CentOS 7.2或者是CentOS 6.8,偏移CentOS 7.2
虚拟主机各IP:node1–10.1.15.40, node2–10.1.15.41 node3–10.1.15.42
node1节点–10.1.15.40,安装haproxy,其它两个节点做后端轮询。
base收录版本1.5,但是马上要废弃了。官方最新版是1.7开发板(演示1.5)
HAproxy的安装
haproxy已经收录到了base仓库,所以我们直接yum安装就可以了,因为我这里实验使用的Centos7系统,所以还是使用YUM,其它发行版本可另行抉择。
如果遇到yum安装报错You could try using –skip-broken to work around the problem
可移除yum.repos.d目录下的所有文件,只留base.repo文件然后yum clean all
再执行yum install
[root@localhost yum.repos.d]# yum install haproxy -y
HAproxy程序环境:
配置文件:/etc/haproxy/haproxy.cfg Unit File: haproxy.service 主程序:/usr/sbin/haproxy 配置文件分两部分组成: global:全局配置段 进程及安全配置相关的参数 性能调整相关的参数 Debug相关的参数 proxies:代理配置段 defaults:为frontend, backend以及listen提供默认配置; frontend:前端,相当于Nginx中的server{ ... }; backend:后端,相当于nginx中的upstream { ... }; listen:前后端的直接组合;
简单实现用haproxy实现后端主机代理,简单均衡
1、> vim /etc/haproxy.cfg 在haprxoy 10.1.15.40主机上修改以下内容
frontend main
bind *:80,*:8080
default_backend web
# static backend for serving up p_w_picpaths, stylesheets and such
backend web
balance roundrobin
server web1 10.1.15.41:80 check
server web2 10.1.15.42:80 check
2、在后端两台主机安装httpd启动服务,给指定网页分别叫backend1和backend2
10.1.15.41
vim /var/www/html
<h1> backend 1 <h1>
10.1.15.42
vim /var/www/html
<h1> backend 2 <h1>
HAproxy相关配置参数全局段:
global配置参数:
进程及安全配置相关的参数:user/uid, group/gid, nbproc, ulimit-n, ca-base, …
log < address > [len < length >] < facility > [ max level [min level]]
定义日志相关配置属性address是日志服务器的地址, [len < length >]是每行日志记录的最大长度
举例:如何记录haproxy的日志呢?
1、 让haproxy服务器启用接收远程主机所传来的日志信息
2、 如果启用local2.,指明local2.日志记录于何处
3、如果启用日志,使用udp和tcp都可以,我们这里使用的udp,把注释去掉
vim /etc/rsyslog.conf 第一步 #Provides UDP syslog reception $ModLoad imudp $UDPServerRun 514 指明日志记录到哪里去 第二步 #Save boot messages also to boot.log local2.* /var/log/haproxy.log systemctl restart rsyslog.service,确保UDP 514端口被监听 [root@localhost log]# cat haproxy.log Nov 12 13:26:24 localhost haproxy[23610]: 10.1.15.85:6703 [12/Nov/2016:13:26:24.829] main web/web1 0/0/0/3/3 200 280 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1"
性能调优相关参数
maxconn < number>:设定单haproxy进程的最大并发连接数;
maxconnrate < number>:设定单haproxy进程每秒所能接受的连接数;
maxsslconn < number>:设定单haproxy进程的ssl连接最大并发连接数;
maxsslrate < number>:单haproxy进程的ssl连接的创建速率上限;
spread-checks <0..50, in percent>
向后端主机做健康状态检测时,该如何散开检测机制
tune.bufsize < number> 缓冲池大小
tune.rcvbuf.client < number> 接收客户端请求时缓冲池大小
tune.rcvbuf.server < number> 接收后端服务器的响应时缓冲池大小
tune.sndbuf.client < number> 向客户端发送响应
tune.sndbuf.server < number> 向服务端发送请求
tune.ssl.cachesize < number> ssl的缓存大小
tune.ssl.lifetime < timeout> ssl的缓存会话的有效时长
Debugging:
debug 尽量输出详细信息
quiet 不输出详细信息
Userlists:定义用户、组及用户列表;
userlist < listname >
group < groupname > [users < user >,< user >,(…)]
user < username > [password|insecure-password < password >]
strong text[groups < group >,< group >,(…)]
Peers:把多个haproxy定义构建为同步集群
peer
peers
其它未尽详细的参数请参考官方帮助文档
http://cbonte.github.io/haproxy-dconv/1.5/configuration.html#3.1
HAproxy相关配置参数代理段:
关于代理段的详细参数在这里就不多说,还是请参考官方文档,太多了看起来头疼
简要说下HAproxy的工作模式”Mode”
Mode可以工作在default,listen.backend和frontend中,用来定义HAproxy到底工作在应用层还是传输层
Mode主要用来定义haproxy的三种工作模型:
tcp:基于layer4实现代理,可代理大多数基于tcp的应用层协议,例如ssh/mysql/pgsql等;
http:工作在应用层,客户端的http请求会被深度解析;
health:工作为健康状态检查响应模式,当请求到达时仅回应“OK”即断开连接;
HAproxy调度算法:
定义负载均衡的算法除了listen和backend段中也可以放在defaults段中,定义格式:
balance < algorithm > [ < arguments > ]
balance url_param [check_post [< max_wait >]]
常见的调度算法
roundrobin:
动态算法:支持权重的运行时调整,支持慢启动;仅支持最大4095个后端活动主机
server后面使用weight来定义权重;
static-rr:
基于权重进行轮询与roundrobin类似静态算法:不支持权重的运行时调整及慢启动;但后端主机数量无限制;
leastconn:
新的连接请求被派发至具有最少连接数目的后端服务器,动态算法,适用于较长时间会话的场景。
source:
将请求的源地址进行hash运算,并与后端服务器的总权重作取模运算后调度至某台服务器;同一IP地址的请求将始终被调度至某特定的服务器,可以使用hash-type修改此特性来确定动态还是静态算法
hash表如何建立映射:除权重取模法,一致性hash
hash-type:
map-based:取模法,hash数据结构是静态数组;
consistent:一致性哈希,哈希的数据结构是“树”;
uri:
对URI的左半部分(“?”之前的部分)或整个URI进行hash运算,并与后端服务器的总权重作取模运算后调度至某台服务器;同一URI的请求将始终被调度至某特定的服务器,静态算法,可以使用hash-type修改此特性;
hdr(< name >):
根据用户请求报文中指定的http首部的值进行调度,常用于实现对同一个虚拟主机的请求始终发往同个backend server。
first:
先到先得,服务器名称标识字符最短的优先调用。一台用完才用第二台,忽略权重。
**演示示例** 更改调度算法为source,把同一IP地址的请求将始终被调度至某特定的服务器 vim /etc/haproxy/haproxy.cfg backend web balance roundrobin //修改为source server web1 10.1.15.41:80 check server web2 10.1.15.42:80 check systemctl reload haproxy.service //测试:http://19.1.15.40 更改调度算法为uri,把同一页面请求通过调度算法发往到后端指定服务器 vim /etc/haproxy/haproxy.cfg backend web balance roundrobin //修改为uri server web1 10.1.15.41:80 check server web2 10.1.15.42:80 check for i in {1..10}; do echo "test page $i at BACKEND 1 " > /var/www/html/test$i.html; done systemctl reload haproxy.service 测试: for i in {1..10}; do curl http://10.1.15.40/test$i.html;done 结果:把同一个被请求到的页面始终发往到指定的后端服务器上 更改调度算法为hdr,把同一浏览器的请求,始终发往到后端指定服务器上 vim /etc/haproxy/haproxy.cfg backend web balance roundrobin //修改为hdr(User-Agent) server web1 10.1.15.41:80 check server web2 10.1.15.42:80 check systemctl reload haproxy.service 测试: for i in {1..10}; do curl http://10.1.15.40/test$i.html;done 结果:只要浏览器一样,请求始终被调度到指定后端服务器上
调整服务器的最大并发连接数,并启用stats页面做认证
定义并发数有两种方法:
一种,全局定义,一种默认定义
vim /etc/haproxy/haproxy.cfg
frontend main //在此下面定义maxconn 10000
bind * :80, * :8080
maxconn 10000
定义stats页面,在代理配置段四项中都可以定义
vim /etc/haproxy/haproxy.cfg
frontend main
bind :80,:8080
maxconn 10000 //最大并发连接数
stats enable // 开启stats页面
stats uri /admin?stats //自定义stats页面
default_backend web //默认的后端主机标识web
stats realm stats\ page\ area //开启认证界面
stats auth admin:admin //认证用户名密码
stats hide-version //隐藏版本信息
stats refresh 5s //指定stats页面5秒刷新一次
stats admin if TRUE //内建访问控制列表
测试:http://10.1.15.40/haproxy?stats
对后端服务器做健康状况检测
check为server的参数,可启动对此server执行健康状态的检测。check借助其额外的参数可实现更精细的监测机制。
inter < delay>:
健康状态检测的时间间隔,单位为毫秒,默认为2000,可以使用fastinter和downinter来根据服务器端状态优化此时间延迟
rise < count>:
健康状态检测中某离线的server从离线状态转换至正常状态需要成功检查的次数
fall < count>:
确认server从正常状态转换为不可用状态需要检查的次数
默认为传输层检测,即探测端口是否能响应。
需要执行应用层检测,则需要
httpchk, smtpchk, mysql-check, pgsql-check, ssl-hello-chk;
vim /etc/haproxy/haproxy.cfg
backend web //下面修改内容
balance roundrobin
server web1 10.1.15.41:80 weight 2 maxconn 5000 check inter 1 rise 1 fall 2
server web2 10.1.15.42:80 weight 1 maxconn 3000 check inter 1 rise 1 fall 2
测试:10.1.15.40/haproxy?stats
对后端服务器做加权轮询
vim /etc/haproxy/haproxy.cfg backend web //在后端主机下列加入 balance roundrobin server web1 10.1.15.41:80 check weight 2 maxconn 5000 cookie web1 server web2 10.1.15.42:80 check weight 1 maxconn 3000 cookie web2 systemctl reload haproxy.service 测试: for i in {1..10}; do curl http://10.1.15.40/index.html;done 结果:权重weight,并发maxconn,指定的值cookie 注意:修改后端服务器的调度算法:一定要重启haproxy的服务,reload是不成功
基于cookie的session绑定
在响应报文中添加cookie信息,下一次的客户请求会带上这个cookie信息,服务器端根据cookie将请求始终定向至后端的某一台服务器,可用于保持session会话。
而cookie信息该怎么插入进来
rewrite: 重新改写原有的所有cookie
insert: 在原有cookie信息当中插入
prefix: 在原有cookie附加为前缀
举例:把基于浏览器的用户会话访问,对当前服务器讲第一次调度到某个主机,那么就调度某主机 vim /etc/haproxy/haproxy.cfg backend web //在后端主机下列加入 balance roundrobin cookie webserver insert nocache indirect server web1 10.1.15.41:80 check weight 2 maxconn 5000 cookie web1 server web2 10.1.15.42:80 check weight 1 maxconn 3000 cookie web2 服务器第一次为某客户度挑选中的主机,会把webserver中的参数值赋值到web1上或者web2上 systemctl reload haproxy.service 测试: for i in {1..10}; do curl http://10.1.15.40;done [root@localhost haproxy]# curl -I 10.1.15.40
自定义haproxy错误页面
vim /etc/haproxy/haproxy.cfg frontend main bind *:80,*:8080 maxconn 10000 stats enable default_backend web stats realm stats\ page\ area stats auth admin:admin stats hide-version stats refresh 5s stats admin if TRUE #errorfile 503 /etc/haproxy/errorfiles/503sorry.http //直接以文件形式显示错误页面 errorloc 503 http://10.1.15.40:9527/errorpagetest.html // 直接以url形式显示错误页面,重定向302 errorloc 503 http://www.baidu.com mkdir /etc/haproxy/errorfiles vim /etc/haproxy/errorfiles/503sorry/http < h1 >sorry page home < h1 > systemctl reload haproxy.service 测试:stop后端所有主机,然后请求haproxy前端主机地址 :10.1.15.40option forwardfor
客户端的请求经前端的代理服务器转发至后端的web服务器,代理服务器在转发时将目标地址改为后端的某台web服务器地址,将源地址由client ip(客户端地址)改为自己面向后端服务器的地址。后端的web服务器若使用默认格式记录日志,则记录的客户端IP地址都为前端的代理服务器地址。这时需要在发往后端的请求报文中添加内容为客户端IP地址的首部,以便后端的web服务器能够正确获取客户端地址。
x-forwardfor
在配置文件默认段里已经定义了转发,所以我们直接用就可以了。
vim /etc/haproxy/haproxy.cfg
defaults
option forwardfor except 127.0.0.0/8
然后修改两台后端主机的httpd.conf文件,vim /etc/httpd/conf/httpd.conf
把LogFormat %h修改为{X-forwarded-For}i
重启服务systemctl restart httpd.service
在haproxy前端主机上刷新下页面。然后在后端主机看日志是否记录的是客户端的真实地址就可以。
tail /var/log/httpd/access.log看请求的是真实的客户端地址功能就实现了。
修改请求或响应报文首部相关:
增加响应报文相关信息
frontend main
rspadd X-Via:\ HAProxy/1,5
rspidel Server.*
rspadd X-Via:\ HAProxy/1,5
客户端请求看一看在Response Headers报文里有没有值:X-Via:HAProxy/1,5
删除响应报文Server相关信息
rspidel Server.*
ACL basics
HAPAroxy的ACL能够通过检测请求报文的首部、响应报文的内容或其他的环境状态信息作出转发决策,增强了其配置弹性。
配置分两步骤:首先定义ACL,即定义一个测试条件,再定义动作,即满足测试条件的情况下执行的某特定动作。
语法格式:
acl < aclname> < criterion> [flags] [operator] [< value>] …
取值类型:
– boolean
– integer or integer range
– IP address / network
– string (exact, substring, suffix, prefix, subdir, domain)
– regular expression
– hex block
匹配的操作符:数值匹配,字符串匹配,逻辑条件等…
注意注意:语法太多,让人很蛋疼,简直太头疼,咋么那么多
注意注意:自定义ACL全部都是小写
四层匹配,举例: vim /etc/haproxy/haproxy.cfg 在 frontend main 中定义 acl myhost src 10.1.15.85 acl myport dst_port 8080 block if !myhost myport 任何人试图去访问8080端口时,但不是来自于myhost主机就全部拒绝 七层匹配,举例: acl text_file path_end -i .txt block if text_file 任何人去试图访问txt文件,结尾不区分大小写的全部拒绝 举例:匹配某个浏览器类型 acl chrome hdr_reg(User-Agent) -i .*chrome.*$ block if chrome
HTTP层访问控制指令
acl valid_method method GET HEAD http-request deny if ! valid_method 举例: acl myhost src 10.1.15.40 http-request deny if url_admin !myhost
动静分离
frontend main *:5000
acl url_static path_beg -i /static /p_w_picpaths /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static //如果上面的条件满足调至backend static主机
default_backend app //否则调至app主机
backend static
balance roundrobin
server static 127.0.0.1:4331 check
round robin balancing between the various backends
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check