node1:扮演调度器(安装HAProxy),node2:扮演后台web服务器节点1(安装nginx),node3:扮演后台web服务器节点2(安装nginx)。有关虚拟机安装后常见操作请看上一篇文章。
先把需要的软件安装好:
node1 ]# yum install -y haproxy
node2 ]# yum install -y nginx
node3 ]# yum install -y nginx
把node2、node3的nginx服务启动起来,添加网页文件(后面可能会写一篇关于nginx的文章)。
对于node1,修改HAP的配置文件(生产环境中,修改配置文件前要先做好备份):
node1 ]# vim /etc/haproxy/haproxy.cfg
保留global段、defaults段,其他配置信息都删掉。添加以下配置:
listen NginxServers
bind *:80
balance static-rr
server N1 node2:80
server N2 node3:80
启动HAP服务:node1 ]# systemctl start haproxy.service
打开浏览器,访问node1节点80端口,刷新网页,可以看到HAP已经能够正常工作!并把HTTP请求按照轮询的方式调度给node2和node3节点的nginx服务。
HAProxy,High Available Proxy,即高可用的代理服务器。要注意的是,这里的高可用不是指HAP服务自身实现了高可用,而是指HAP原生自带对后端服务器的健康状态检查机制,若发现某个BackEnd Server不可用,服务请求就不会再发往此后端节点。
HAP是一种软件实现的负载均衡器,因此它工作为用户空间的一个进程,基于套接字与客户端,后端主机进行通信。基于此,HAP能够很好地支持对HTTP请求的七层调度,对HTTP请求实现诸如“动静分离”,“HTTP方法分离”等。另外,HAP支持通过模拟方式实现四层调度,四层调度性能应该稍差。
总的来说,HAP是目前最主流的七层调度器实现方案之一,具有较好的性能以及配置多样性。
HAP将配置文件分为两大段。
Proxy段:用来定义与调度的具体实现方式,Proxy段具体包括
global:全局配置段常用变量
进程及安全配置相关参数:
chroot /var/lib/haproxy:禁锢根,haproxy进程以此目录作为根目录,防止haproxy进程被劫持而设定的安全性配置
user haproxy: 运行haproxy进程的用户和组
group haproxy:
daemon:表示haproxy运行于后台守护进程,而非前台(调试模式)
nbproc <number>:指明要启动的haproxy进程数量; haproxy默认工作于基于事件驱动的单进程模型(也可以指明为启动多进程,官方并不建议)
ulimit-n <number>:每个haproxy进程能够打开的最大文件数:此参数非常重要,因为每一个连接都需要打开一个socket file,因此该值至少大于进程数 * 每个进程接受的最大连接数。haproxy能够根据运行情况自行调整该值,一般不需要定义
log:定义全局的syslog服务器,用于将haproxy产生的日志发往并存储
log <address> <facility> [level]
好像现在HAP默认关闭了日志记录,要启用还挺麻烦,大家可以参考这篇文章作者的启用方式,测试有效!HAProxy启用日志
性能调整相关参数
maxconn 4000:单个haproxy进程所能接受的最大并发连接数
maxpipes:使用pipe机制实现内核级tcp报文重组;每进程能够使用的最大pipe数量;haproxy能够自动调整
spread-checks <0..50>:百分比数字,用于打散健康状态监测的时间点。例如每隔60秒对后端100台主机进行健康状态检查,此值设定为20表示,某台主机进行完一次检查后,下一次的检查时间可能是(48s,72s)内的任何一个时间,这样就打散了每台主机的检查时间,从而减轻了由于health-check带来的性能消耗
Debug相关参数
debug:详细输出日志信息(调试模式时)
quiet:简化日志的输出信息
下面介绍Proxy段中的常用变量:这些变量可用于listen,frontend,backend中的一个或多个
1、bind:可用在listen,frontend;用于指明haproxy服务监听的套接字地址
# bind <address>:<port_range>,....[param*]
e.g. bind *:80 ssl, 192.168.1.7/24:8080
表示haproxy监听于任意ipv4地址的80端口(外部访问),以及192.168.1.7:8080这一地址(内部访问),同时,并且受理外部请求时必须是https连接。
2、balance:可用在listen,backend,default;用于指明对后端server使用的调度算法
# balance <algo> [params]
<algo>: 表示调度算法,常用的调度算法如下:
roundrobin [加权]轮询
动态算法,支持权重的运行时调整以及慢启动机制;最多4095个后端主机
慢启动:若共6000个连接,3台后端服务器,权重均相同,则每台处理2000个连接。此时新增一台服务器,那么应该每台处理1500个连接,所以大量的新连接都会给新增的那台,极易造成压力过大,慢启动则避免了这点
static-rr [加权]轮询
静态算法:不支持权重的运行时调整以及慢启动机制;后端主机无数量限制
leastconn 最少连接
推荐使用在较长时间会话场景中,如LDAP,MYSQL协议
first 依次处理请求
每台后端主机可定义自己的maxconn。first算法根据maxconn的从大到小为后端主机排序,然后每次都将连接请求发给maxconn最大的那台主机,直到达到它的maxconn,才调度给下一台sever。
first算法的好处是能够节约虚拟机资源(backendserver一般是虚拟机实例),按需决定启动多少台虚拟机,坏处是配置麻烦,单台虚拟机处理太多连接压力过大。
source 源地址hash ---> 会话绑定
uri 目标地址hash ---> 提高缓存命中率
采用哈希调度算法时,NEW连接首次被调度至哪里可用hash-type命令由两种方式指定:
# hash-type <method>
map-based 取模法
consistent 一致性哈希
hdr(<name>)
对于每个http请求,此处name指定的http报文首部会被取出做hash计算。然后再有相同的请求时,调度给同一台主机。source和uri是它最常用的hash调度子类
e.g. 对于某个站点,可能由多个域名,如jd.com,www.jd.com,对于请求报文中不同Host,都始终调度给同一台backend_server
balance hdr(Host)
hash-type map-based
3、log:用在default,frontend,backend,listen;定义日志的记录位置,做多定义两个位置。
# log global || # log <address> <facility> [level] || # no log
分别表示使用全局配置中的log记录位置或使用自定义的日志记录位置或不记录日志
4、capture request header;用在listen,frontend;用于添加指定请求报文首部信息记录于日志中
# capture request header <name> len <length>
e.g. capture request header User-Agent len 10
5、capture response header ;用在listen,frontend;用于添加指定响应报文首部信息记录于日志中
# capture response header <name> len <length>
e.g. capture response header Cache-Control len 5
6、compression;用在listen,frontend,backend;用于压缩报文中的body部分
# compression algo <algorithm>
# compression type <mime type>
支持的压缩algo:gzip,deflate
mime type:通常只压缩文本类信息
e.g. compression algo gzip
compression type text/html
注意:compression用在frontend中表示压缩与客户端通信报文中的body,用在backend中则表示压缩与后端主机通信过程中报文的body
7、server:用于listen,backend;用来定义一个后端主机
# server <name> <addr:port> [params*]
<name>:HAProxy中服务器的唯一标识,必给
<addr:port>:后端主机监听的ip地址及端口
[params*]:定义一个主机时同时可指定的可选参数
backup:设定为备用服务器,仅在LB中其他服务器均不可用时才接受请求。类似于nginx-upstream定义主机时的down,用于维护时下线主机
check:对后端主机作基于tcp端口的四层健康状态检测;check后可跟辅助参数,也可仅适用默认值
inter<delay>:每隔多久做一次检测
fall<count>:连续多少次失败从LB中移除该主机
rise<count>:连续多少次成功从LB中添加该主机
maxconn:指定该服务器支持的最大连接数
maxqueue:指定该服务器支持的最大等待队列长度
cookie <name>:本台server的cookie信息,可任意指定
redir <prefix>:将发往此服务器的所有GET,HEAD请求重定向至指定地址
weight <weight>:指定权重
8、httpchk:用于listen,backend;基于7层http协议对后端主机进行状态检测
# option httpchk <uri>
e.g. option httpchk /login.html
9、cookie:用于listen,backend;设定基于cookie的会话绑定
# cookie <name> [ insert | prefix | rewrite ] [params*]
<name>:cookie标签的名字
insert:插入某主机的cookie信息
prefix:在cookie前添加信息
rewrite:重写cookie
e.g. cookie WEBNODES insert indirect nocache
server node1 172.16.100.67:8100 check cookie node1
server node1 172.16.100.67:8100 check cookie node1
随后,在HTTP请求报文中可以看到添加的cookie信息,并且一段时间内来自同一cip的请求被调度至了同一台server
10、mode:用在default,frontend,backend,listen;指明haproxy的工作模式
# mode {tcp | http}
http:后端LB集群为web server时,应设定mode为http模式,此时支持各种高级分析功能
tcp:当后端LB集群为mysq等非基于http协议通信的服务时,应使haproxy工作于tcp模式,此时可调度mysql,ldap,ssh,ssl等协议的通信报文
11、forwardfor:在后端web server的日志文件中记录下CIP而非DIP()
e.g. option forwardfor except 127.0.0.1/8
同时修改后端httpd配置文件中的Logformat中 %h为 %{X-Forwarded-For}i
12、option http-keep-alive
option http-server-close
前者表示启用与client端通信时的长连接功能,启用此功能时,一般需要同时启用后者,表示允许HAProxy关闭非活动状态的长连接。
13、rspadd <search> haproxy在给client的响应报文中添加某自定义header;用于listen,backend中
# rspdel <search> haproxy在给client的响应报文中查找某hearder并删除
# rspidel <search> haproxy在给client的响应报文中基于正则表达式查找某hearder并删除
e.g. 在响应报文中,一般我们不想让客户端知道后端real server的信息,可用以下指令完成
rspidel ^Server:.*
若要实现复杂的调度能够,如“动静分离”,则需要定于ACL相关变量:
1、 acl:用在frontend中,定义一条acl匹配规则
# acl <aclname> <criterion> [flags] [operator] <value> ...
criterion:acl匹配检查规则
四层
dst IP
dst_port PORT
src IP
src_port PORT
七层
method <http_method>:指明http报文中的请求方法
path:URI精确匹配
path_beg:URI开头匹配
path_end:URI结尾匹配
path_reg:URI正则表达式匹配
url:URL精确匹配
url_beg:URL开头匹配
url_end:URL结尾匹配
url_end:URL正则表达式匹配
hdr <name><value>:请求报文中某个header值的精确匹配
hdr_beg <name><value>:请求报文中某个header值的开头匹配
hdr_end <name><value>:请求报文中某个header值的结尾匹配
flags: -i 表示匹配检查时忽略字符大小写
value:匹配检查的对象
2、use_backend:用于frontend中,表示当满足某个acl时,调用指定的backend <name>
# use_backend <backend> [if | unless <acl_name>]
3、default_backend:用于frontend中,指明默认将请求调度给哪个backend <name>
# deault_backend <backend>
4、block:用于frontend中,符合acl规则时,阻止访问请求
# block if | unless <acl_name>
1、启用HAProxy内置管理页面
listen stats *:9001 定义访问管理页面的IP:PORT
stats enable 启用此功能
stats uri /haproxyadmin 定义访问的URI
stats realm "ADMIN AREA" 页面提示信息,要求用户登录后访问
stats auth admin:123456abc 设定登录用户的账号密码
stats admin if TRUE 如果登录成功,在此页面开启管理接口权限(默认只能查看运行状态统计信息)
2、HAProxy实现模拟实现四层调度
listen MySQLsrvs
bind *:20002
balance leastconn 使用最少连接调度算法
mode tcp 定义为四层调度
server sqlnode1 172.16.100.67:3306 check
server sqlnode2 172.16.100.68:3306 check
3、配置一个能够实现动静分离的调度服务器:
frontend dirctor
bind *:80,*:8080
acl picreq path_end -i .jpg .jepg .bmp
acl phpreq path_end -i .php
acl putreq method put
acl stop src 222.222.222.0/24
use_backend picsrvs if picreq
use_backend phpsrvs if phpreq
use_backend putnode if putreq
default_backend stasrvs
block if stop
backend picsrvs
balance roundrobin
server picnode1 172.16.100.67:8100 check weight 1 maxconn 2000
server picnode2 172.16.100.77:8100 check weight 2 maxconn 2000
backend phpsrvs
balance roundrobin
cookie PHP insert indirect nocache
server phpnode1 172.16.100.68:8100 check maxconn 300 cookie phpnode1
server phpnode2 172.16.100.78:8100 check maxconn 300 cookie phpnode2
backend putnode
balance static-rr
server node 172.16.100.69:8100 check
backend stasrvs
balance roundrobin
server httpnode1 172.16.100.70:8100 check maxconn 2000 weight 1
server httpnode2 172.16.100.80:8100 check maxconn 2000 weight 2