Haproxy 1.8.x 的安装与配置解析
一、Haproxy简介
1、Haproxy的介绍
HAProxy是法国开发者Willy Tarreau开发的一个开源软件,是一款具备高并发、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计。
2、Haproxy的功能
HAProxy是TCP/HTTP反向代理服务器,尤其适合于高可用性高并发环境
• 可以针对HTTP请求添加cookie,进行路由后端服务器
• 可平衡负载至后端服务器,并支持持久连接
• 支持基于cookie进行调度
• 支持所有主服务器故障切换至备用服务器
• 支持专用端口实现监控服务
• 支持不影响现有连接情况下停止接受新连接请求
• 可以在双向添加,修改或删除HTTP报文首部
• 支持基于pattern实现连接请求的访问控制
• 通过特定的URI为授权用户提供详细的状态信息
二、Haproxy安装
1、编译安装过程
(1) 准备源码包,可到官网下载 https://www.haproxy.org
[root@centos7 ~]# ll haproxy-1.8.20.tar.gz -rw-r--r-- 1 root root 2083917 Jan 10 20:39 haproxy-1.8.20.tar.gz
(2) 安装相应依赖包
[root@centos7 ~]# yum install -y gcc gcc-c++ pcre pcre-devel openssl openssl-devel systemd-devel
(3) 解压源码包,并进行编译
[root@centos7 ~]# tar -zxvf haproxy-1.8.20.tar.gz [root@centos7 ~]# cd haproxy-1.8.20/ [root@centos7 haproxy-1.8.20]# make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy [root@centos7 haproxy-1.8.20]# make install PREFIX=/usr/local/haproxy [root@centos7 haproxy-1.8.20]# cp haproxy /usr/sbin/
(4) 创建启动脚本
[root@centos7 haproxy-1.8.20]# vim /usr/lib/systemd/system/haproxy.service [Unit] Description=HAProxy Load Balancer After=syslog.target network.target [Service] ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /usr/local/haproxy/run/haproxy.pid ExecReload=/bin/kill -USR2 $MAINPID [Install] WantedBy=multi-user.target
(5) 创建用户与相关目录以及配置文件
[root@centos7 haproxy-1.8.20]# useradd -r -s /sbin/nologin haproxy [root@centos7 haproxy-1.8.20]# mkdir /etc/haproxy [root@centos7 haproxy-1.8.20]# mkdir /usr/local/haproxy/run [root@centos7 haproxy-1.8.20]# mkdir /var/lib/haproxy [root@centos7 haproxy-1.8.20]# chown -R haproxy:haproxy /var/lib/haproxy/ [root@centos7 haproxy-1.8.20]# vim /etc/haproxy/haproxy.cfg
[root@centos7 haproxy-1.8.20]# cat /etc/haproxy/haproxy.cfg global maxconn 100000 chroot /usr/local/haproxy #stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #uid 981 #gid 981 user haproxy group haproxy daemon #nbproc 4 #cpu-map 1 0 #cpu-map 2 1 #cpu-map 3 2 #cpu-map 4 3 pidfile /usr/local/haproxy/run/haproxy.pid log 127.0.0.1 local3 info defaults option http-keep-alive option forwardfor maxconn 100000 mode http timeout connect 300000ms timeout client 300000ms timeout server 300000ms listen stats mode http bind 0.0.0.0:9999 stats enable log global stats uri /haproxy-status stats auth haadmin:q1w2e3r4ys listen web_port bind 0.0.0.0:80 mode http log global server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
(6) 启动haproxy服务
[root@centos7 haproxy-1.8.20]# systemctl start haproxy [root@centos7 haproxy-1.8.20]# ps -ef|grep haproxy root 58693 1 0 23:29 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /usr/local/haproxy/run/haproxy.pid haproxy 58697 58693 0 23:29 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /usr/local/haproxy/run/haproxy.pid root 58708 6403 0 23:29 pts/0 00:00:00 grep --color=auto haproxy
三、Haproxy配置项解析
1、global 全局配置段
• chroot #锁定运行目录 • deamon #以守护进程运行 • stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket文件 • user, group, uid, gid #运行haproxy的用户身份 • nbproc #开启的haproxy进程数,与CPU保持一致 • nbthread #指定每个haproxy进程开启的线程数,默认为每个进程一个线程 • cpu-map 1 0 #绑定haproxy 进程至指定CPU • maxconn #每个haproxy进程的最大并发连接数 • maxsslconn #SSL每个haproxy进程ssl最大连接数 • maxconnrate #每个进程每秒最大连接数 • spread-checks #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间 • pidfile #指定pid文件路径 • log 127.0.0.1 local3 info #定义全局的syslog服务器;最多可以定义两个
2、proxies 代理配置段
defaults [<name>] #默认配置项,针对以下的frontend、backend和listen生效,可以多个name
• option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器 • option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 • option http-keep-alive 60 #开启会话保持 • option forwardfor #开启IP透传 • mode http #默认工作类型 • timeout connect 60s #转发客户端请求到后端server的最长连接时间(TCP之前) • timeout server 600s #转发客户端请求到后端服务端的超时超时时长(TCP之后) • timeout client 600s #与客户端的最长空闲时间 • timeout http-keep-alive 120s #session 会话保持超时时间,范围内会转发到相同的后端服务器 • timeout check 5s #对后端服务器的检测超时时间,一般在服务器组配置
frontend <name> #前端servername,类似于Nginx的一个虚拟主机server
• bind [<address>]:<port_range> [, ...] [param*] #指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中 • mode http/tcp #指定负载协议类型 • use_backend backend_name #调用的后端服务器组名称
示例:
frontend WEB_PORT bind 192.168.27.7:80 mode tcp use_backend backend_name
backend <name> #后端服务器组,等于Nginx的upstream
• mode http/tcp #指定负载协议类型 • option #配置选项,可加httpchk,smtpchk, mysql-check, pgsql-check,ssl-hello-chk等方法,可用于实现更多应用层检测功能 • server #定义后端real server,后可接 check 对指定real进行健康状态检查,默认不开启
check #对指定real server进行健康状态检查,默认不开启 • addr IP #可指定的健康状态监测IP • port num #指定的健康状态监测端口 • inter num #健康状态检查间隔时间,默认2000 ms • fall num #后端服务器失效检查次数,默认为3 • rise num #后端服务器从下线恢复检查次数,默认为2 • weight #默认为1,最大值为256,0表示不参与负载均衡 • backup #将后端服务器标记为备份状态 • disabled #将后端服务器标记为不可用状态 • redirect prefix http://www.xxx.com/ #将请求临时重定向至其它URL,只适用于http模式 • mbacklog axconn <maxconn> #当前后端server的最大并发连接数 • <backlog> #当server的连接数达到上限后的后援队列长度
frontend WEB_PORT_80 bind 192.168.27.7:80 mode http use_backend web_prot_http_nodes backend web_prot_http_nodes mode http option forwardfor server web1 192.168.27.17:8080 weight 1 check inter 3000 fall 3 rise 5 server web2 192.168.27.27:8080 weight 1 check inter 3000 fall 3 rise 5 server web2 192.168.27.37:8080 check inter 3000 fall 3 rise 5 backup
listen <name> #将 frontend 和 backend 合并在一起配置
listen WEB_PORT_80 bind 192.168.27.7:80 mode http option forwardfor server web1 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server web2 192.168.27.27:8080 check inter 3000 fall 3 rise 5
注:name字段只能使用 " - "、" _ "、" . "、" : ",并且严格区分大小写。
四、Haproxy的调度算法
通过 balance 指明对后端服务器的调度算法,配置在listen或backend。调度算法有以下几种:
1、first
根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置;
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #可以为tcp或http balance first option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
2、static-rr
基于权重的轮询静态调度算法,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制;
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #可以为tcp或http balance static-rr option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
3、roundrobin
基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的 rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法;
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #可以为tcp或http balance rountrobin option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
4、leastconn
加权的最少连接动态调度算法,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度,比较适合长连接的场景使用,比如MySQL等场景;
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #可以为tcp或http balance leastconn option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
5、source
源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景;
• map-based:取模法,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,不支持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变;
• consistent:一致性哈希,该hash是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动;
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #可以为tcp或http balance source hash-type consistent option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
6、uri
基于对用户请求的uri做hash并将请求转发到后端指定服务器;
• map-based:取模法
• consistent:一致性哈希
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #只能是http balance uri hash-type consistent option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
7、url_param
对用户请求的url中的<params>部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server;
假设url=http://www.xx.com/index.php?k1=v1&k2=v2,则url_param="k1=v1&k2=v2";
• map-based:取模法
• consistent:一致性哈希
#假设url=http://192.168.27.7/index.html?name=tom listen web_prot_http_nodes bind 192.168.27.7:80 mode http #只能是http balance url_param hash-type consistent option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
8、hdr
针对用户每个http头部(header)请求中的指定信息做hash,此处由<name>指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度;
• map-based:取模法
• consistent:一致性哈希
listen web_prot_http_nodes bind 192.168.27.7:80 mode http #只能是http balance hdr(User_Agent) hash-type consistent option forwardfor server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
9、rdp-cookie
对远程桌面的负载,使用cookie保持会话;
• map-based:取模法
• consistent:一致性哈希
listen RDP bind 192.168.27.7:3389 mode tcp #只能是tcp balance rdp_cookie hash-type consistent option forwardfor server 192.168.27.17 192.168.27.17:3389 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:3389 check inter 3000 fall 3 rise 5
五、部分配置实例
1、基于cookie实现的session保持
cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
<name>:cookie名称,用于实现持久连接
rewrite:重写
insert:插入
prefix:前缀
nocache:当client和hapoxy之间有缓存时,不缓存cookie
listen web_prot_http_nodes bind 192.168.27.7:80 mode http cookie SERVER-COOKIE insert indirect nocache option forwardfor server 192.168.27.17 192.168.27.17:8080 cookie web1 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 cookie web2 check inter 3000 fall 3 rise 5
2、Haproxy状态页实现
• stats enable #基于默认的参数启用stats page • stats hide-version # 隐藏版本 • stats refresh <delay> # 设定自动刷新时间间隔 • stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats • stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics 此处\ 为转义空格 • stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication • stats refresh 5s #定义页面自动刷新间隔时间 • stats admin { if | unless } <cond> #启用stats page中的管理功能
listen stats bind 192.168.27.7:9009 stats enable stats hide-version stats uri /haproxy-status stats realm HAPorxy\ Stats\ Page stats auth haadmin:123456 stats auth admin:123456 #可以有多个 stats refresh 30s stats admin if TRUE
3、Haproxy日志配置
在haproxy配置文件default配置项定义: log 127.0.0.1 local{1-7} info #基于syslog记录日志到指定设备,级别有(err、warning、info、debug) 配置rsyslog: $ModLoad imudp $UDPServerRun 514 local3.* /var/log/haproxy.log 配置HAProxy: listen web_port bind 127.0.0.1:80 mode http log global option tcplog #允许记录tcp连接的状态和时间 server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5 重启rsyslog服务与haproxy服务
4、三种后端服务器的监测
(1) 基于四层传输端口监测
listen web_prot_http_nodes bind 192.168.27.7:80 mode http log global option forwardfor server 192.168.27.17 192.168.27.17:8080 check port 9000 addr 172.168.27.17 inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check port 9000 addr 172.168.27.27 inter 3000 fall 3 rise 5
(2) 基于指定URI 做状态监测
listen web_prot_http_nodes bind 192.168.27.7:80 mode http log global option forwardfor option httpchk GET /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0 #基于指定URL server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
(3) 基于指定URI的request请求头部内容做状态监测
listen web_prot_http_nodes bind 192.168.27.7:80 mode http log global option forwardfor option httpchk HEAD /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0\r\nHost:\ 192.168.27.7 #通过request获取的头部信息进行匹配进行健康检测 server 192.168.27.17 192.168.27.17:8080 check inter 3000 fall 3 rise 5 server 192.168.27.27 192.168.27.27:8080 check inter 3000 fall 3 rise 5
5、自定义错误页面
• errorfile 500 /usr/local/haproxy/html/500.html #自定义错误页面跳转 • errorloc 503 http://192.168.7.103/error_page/503.html #自定义错误页面跳转
6、基于acl+文件后缀实现动静分离
listen web_port bind 192.168.27.7:80 mode http acl php_server path_end -i .php use_backend php_server_host if php_server acl image_server path_end -i .jpg .png .jpeg .gif use_backend image_server_host if image_server default_backend default_host backend default_host mode http server web1 192.168.27.17:8080 check inter 2000 fall 3 rise 5 backend php_server_host mode http server web1 192.168.27.27:8080 check inter 2000 fall 3 rise 5 backend image_server_host mode http server web1 192.168.27.37:8080 check inter 2000 fall 3 rise 5
7、acl匹配访问路径
listen web_port bind 192.168.27.7:80 mode http acl static_path path_beg -i /static /images /javascript use_backend static_path_host if static_path default_backend default_host backend default_host mode http server web1 192.168.27.17:8080 check inter 2000 fall 3 rise 5 backend static_path_host mode http server web1 192.168.27.27:8080 check inter 2000 fall 3 rise 5
8、基于http策略的访问控制
listen web_port bind 192.168.27.7:80 mode http acl badguy_deny src 192.168.4.1 http-request deny if badguy_deny http-request allow default_backend default_host backend default_host mode http server web1 192.168.27.17:8080 check inter 2000 fall 3 rise 5 backend static_path_host mode http server web1 192.168.27.27:8080 check inter 2000 fall 3 rise 5
9、https的配置
#web server http frontend web_server-http bind 192.168.27.7:80 mode http redirect scheme https if !{ ssl_fc } #把80端口的请求重向定443 use_backend web_host #web server https frontend web_server-https bind 192.168.27.7:443 ssl crt /usr/local/haproxy/certs/haproxy.pem #crt后的证书文件为PEM格式,且同时包含证书和所有私钥 mode http use_backend web_host backend web_host mode http http-request set-header X-Forwarded-Port %[dst_port] #向后端传递用户请求的端口 http-request add-header X-Forwarded-Proto https if { ssl_fc } #向后端传递用户请求的协议 server web1 192.168.27.17:8080 check inter 2000 fall 3 rise 5 server web2 192.168.27.27:8080 check inter 2000 fall 3 rise 5
# mkdir /usr/local/haproxy/certs # cd /usr/local/haproxy/certs # openssl genrsa -out haproxy.key 2048 # openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.xxx.com" # cat haproxy.key haproxy.crt > haproxy.pem #将私钥和证书导入到一个文件中 # openssl x509 -in haproxy.pem -noout -text #查看证书
10、Haproxy后端服务器的动态上下线
# yum install socat # echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock # echo "get weight web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock # echo "disable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock # echo "enable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock