配置要点
配置时要考虑的问题
- haproxy选择哪种http事务模型
- 静态web的适合长连接
- 动态app的适合短连接
- haproxy的对外最大连接数设置
- 综合考虑,各个后端节点并发之和,以及各个节点的可排队队列数
- haproxy的各类超时时间设置
- 连接超时
- 请求超时
- 传输超时
- 超时重试
- haproxy连接重用的选择
- 是否为了提供效率,对连接进行重用,牺牲部分安全性;
- haproxy调度算法的选择
- 是否开启多进程,多实例
- haproxy一般单实例即可;
- 是否设置cookie和stick table
- 调度的粘性上,选择设置cookie,或stick table
- haproxy的状态页,建议开启,设置合理权限
- 客户端ip透传,建议开启,X-Forwarded-For
1、事务模型
后端是静态web时,响应速度一般较快,建立连接的时间占比大,频繁建立释放连接浪费资源,因此采用keep-alive模型
后端是动态应用服务器时,响应速度一般较慢,建立连接时间占比不大,反而空闲连接浪费资源,因此采用server-close模型
2、并发设置
haproxy的对外提供的最大并发连接数,应该小于等于后端所有节点的并发连接之和,
在考虑了每个后端节点都设置了等待队列的情况下,haproxy对外总的最大并发也要考虑到每个节点的等待队列大小
3、超时时间
haproxy连接两端,对外的客户端,对内的服务端,两端都有不同的超时时间,如:和后端建立连接的超时时间、健康探测时超时时间,客户端长连接超时时间等,都需要根据实际情况合理设置
4、连接重用
和后端节点的空闲tcp连接,是否设置重用,需要平衡安全性,效率,综合考虑进行设置
5、调度算法的选择
根据后端节点的角色,处理能力等进行设置,静态web一般使用加权轮询,动态应用服务及mysql等长连接的应用一般用最小连接,
调度算法优先级低于cookie,在设置了cookie请求下,相关请求会根据cookie进行调度,只有新的不相关请求进来,或长连接失效时,会利用调度算法重新选择调度
6、是否多进程
haproxy单进程,事件驱动,一般不需要开启多进程
7、cookie和stick table
都是为了解决会话绑定问题,将同一客户端的相关连的请求调度到同一个后端节点上,以便每次请求都能找到会话信息;当后端节点利用共享会话服务器的情况下,haproxy也就无须设置此2项
配置文件详解
配置文件结构
- global:设置haproxy进程相关属性;
- default:设置可以被fronted,backend,listend继承的配置,
- listen:等效于一组fronted+backend配置
- fronted:对外开放端口,并发数等
- backend:后端节点信息,健康检测,调度算法,cookie 设置等
global配置段示例
global
daemon
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
stats socket /var/lib/haproxy/stats
默认配置文件
[root@host2 ~]# vim /etc/haproxy/haproxy.cfg
# 全局配置段,配置进程属性相关信息
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
# 日志记录到本机local2设置,需要在/etc/rsyslog.conf中配置local2对应的文件路径,如/var/log/haproxy
chroot /var/lib/haproxy
# 限制haproxy的活动目录
pidfile /var/run/haproxy.pid
# pid文件路径
maxconn 4000
# 前端对外的最大并发,默认4000较小
user haproxy
group haproxy
daemon
# 进行以daemon方式运行,用户和组为haproxy
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# 开启管理socket
# 默认配置段,会被listen和backend段继承的配置;
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
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
# 模式默认http代理
# 日志采用全局日志;
# 不记录空日志
# http事务模型是server-close
# 透传客户端ip,除了本机地址;
# cookie模式下,应被调度到的某节点down掉,重新选择节点调度;
# 重试次数3
# 各类超时时间;
# 最大并发连接数;
# 定义个前端;分别将动静请求转发给2个后端服务器组;
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:5000
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app
# 定义了2个后端服务器组,和调度算法,启用健康检测;
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
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
示例配置
1、配置haproxy,注意:haproxy配置文件,中文注释会报错!
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 20000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
spread-checks 2
# 增大了并发数到20000
# spread-checks 后端节点多时,精确的每过几秒集中检测一下,会压力较大,因此采用在精确时间点的前后2%的时间端内进行检测;官网建议2%-5%
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
timeout http-request 2s
timeout queue 3s
timeout connect 1s
timeout client 10s
timeout server 2s
timeout http-keep-alive 10s
timeout check 2s
maxconn 18000
# 修改了一些默认的超时时间
frontend http-in
bind *:80
mode http
log global
capture request header Host len 20
capture request header Referer len 60
acl url_static path_beg -i /static /images /stylesheets
acl url_static path_end -i .jpg .jpeg .gif .png .ico .bmp .css .js
acl url_static path_end -i .html .htm .shtml .shtm .pdf .mp3 .mp4 .rm .rmvb .txt
acl url_static path_end -i .zip .rar .gz .tgz .bz2 .tgz
use_backend static_group if url_static
default_backend dynamic_group
# 对外开放一个80的http服务,
# 截取请求报文的host和referer头部字段
# 定义4个同名的acl,匹配静态资源的请求,之间是或关系;满足一个即可
# 根据acl定义,被匹配到是静态资源的转发给静态服务器组,其余的交给动态服务器组;
backend static_group
balance roundrobin
option http-keep-alive
http-reuse safe
option httpchk GET /index.html
http-check expect status 200
server staticsrv1 192.168.100.62:80 check rise 1 maxconn 5000
server staticsrv2 192.168.100.63:80 check rise 1 maxconn 5000
# 定义静态服务器组;采用长连接,连接重用用safe级别,检测页面是/index.html,依靠200状态码判断是否健康
定义了2个后端节点,每个节点最大连接5000,连续探测1次正常就可以重新标记为正常;
backend dynamic_group
cookie appsrv insert nocache
balance roundrobin
option http-server-close
option httpchk GET /index.php
http-check expect status 200
server appsrv1 192.168.100.60:80 check rise 1 maxconn 3000 cookie appsrv1
server appsrv2 192.168.100.61:80 check rise 1 maxconn 3000 cookie appsrv2
# 定义后端组,设置cookie,cookie的变量名是appsrv,insert是在原有响应报文头部插入模式,此外还有prefix追加在头部,rewrite覆盖改写等2种模式;
# 调度算法轮询, http事务模式是server-close,探测页面/index.php,判断依据是200的状态码,
# 定义2个后端节点,每个节点最大并发3000,每个节点的标识符即cookie对应的值分别是appsrv1 appsrv2
listen report_stats
bind *:8081
stats enable
stats hide-version
stats uri /hastats
stats realm "pls enter your name"
stats auth admin:admin
stats admin if TRUE
# listen是等效fronted和backend结合的写法
# 启用状态页,隐藏版本号,定义uri和提示符,用户名和密码,端口在8081
2、准备2个后端节点
yum install -y httpd php php-fpm
systemctl start httpd;systemctl enable httpd
systemctl start php-fpm
# 安装httpd,php,php-fpm
vim /var/www/html/index.php
[root@host4 ~]# cat /var/www/html/index.php
<h1>response from webapp 192.168.80.103</h1>
<?php
session_start();
echo "Server IP: "."<font color=red>".$_SERVER['SERVER_ADDR']."</font>"."<br>";
echo "Server Name: "."<font color=red>".$_SERVER['SERVER_NAME']."</font>"."<br>";
echo "SESSIONNAME: "."<font color=red>".session_name()."</font>"."<br>";
echo "SESSIONID: "."<font color=red>".session_id()."</font>"."<br>";
?>
[root@host3 ~]# cat /var/www/html/index.php
<h1>response from webapp 192.168.80.102</h1>
<?php
session_start();
echo "Server IP: "."<font color=red>".$_SERVER['SERVER_ADDR']."</font>"."<br>";
echo "Server Name: "."<font color=red>".$_SERVER['SERVER_NAME']."</font>"."<br>";
echo "SESSIONNAME: "."<font color=red>".session_name()."</font>"."<br>";
echo "SESSIONID: "."<font color=red>".session_id()."</font>"."<br>";
?>
# 准备php文件,2个节点会生成不同的session值
3、直接访问后端节点时,检查cookie
4、重启haproxy配置生效,通过haproxy访问时
可以看到多出一个appsrv字段,值是被调度到的appsrv1,第一个节点的标识符,通过这个cookie字段,客户端的后续请求,携带此cookie,haproxy就可以根据它一直将其调度到第一个节点;
cookie与session简单理解:当客户端第一次请求服务时,服务端会为其生成一个sessionid,sessionid的值各不相同,这个sessionid关联了这个客户端的各种信息,如登陆状态,用户权限等,sessionid和其值保存在服务端,多个客户端的session共同存储在服务端端,相当于服务端的一个用户信息检索数据表;假设某客户端生成的sessionid值是xxx,那么服务器发回客户端时,就会发送一个键值对,sessionid=xxx,作为客户端的cookie;客户端收到后会存储在本地,再次请求时都会携带该cookie,服务端收到请求后根据sessionid=xxx就可以检索到其对应的状态信息,不同用户的sessionid不同,从而达到了区分客户端,并能记录每个客户端不同状态信息的效果;cookie就是一堆k-v类型的键值对,sessionid只是其中一种;
配置文件指令
https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4.1
官网文档上:各个指令的语法和配置示例,
balance
共9种调度算法:
- roundrobin 加权轮询,可动态修改权重
- static-rr 静态加权轮询,运行时不可修改权重
- leastconn
- source 源地址hash
- uri 适用缓存服务器
- url_param 基于用户id进行hash,然后调度
- hdr(name) 基于指定的请求头部调度,一般采用hdr(host)基于主机头调度
- rdp-cookie
- rdp-cookie(name)
hash-type
- consistent:一致性hash
- map-based
bind
fronted段,绑定到哪个端口;
mode
- tcp
- http
log
log global
log <address> <facility> [<level> [<minlevel>]]
capture request/response header
常用的捕获头部字段示例:
capture request header Host len 15
capture request header X-Forwarded-For len 15
capture request header Referer len 15
capture response header Content-length len 9
capture response header Location len 15
maxconn
use_backend
default_backend
其他
- server
- default-server
- option httpchk
- stats
- option forwardfor
- errorfile 错误页面相关
- cookie 和option redispatch
- reqadd和 rspadd
- 超时时间相关
- http过滤,http-request:https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4-http-request
- tcp过滤 tcp-request tcp-response
acl
https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7
acl常用于,匹配区分uri,如区分动态和静态请求,然后用use_backend指令,转发给不同的后端组;
acl语法:
acl <aclname> <criterion> [flags] [operator] [<value>] ...
aclname:指定acl的名称,在引用时区分大小写。可随意指定,且多个acl指令可以指定同一个aclname,这表示"或"的逻辑关系。
flags:可选项,表示标识位。一般会用到的标识位只有"-i",表示不区分大小写。
operator:可选项,某些操作符,有"eq"、"ge"、"gt"、"le"、"lt",表示数学上的等于、大于、小于。
<criterion>:指定检查标准,即检查方法。
value:根据criterion的不同,值的类型不同。
四层常用检查项
src <ip>
src_port <port or port_ranges>
dst <ip>
dst_port <port or port_ranges>
七层常用检查项
hdr(Host) www.b.com
hdr_reg(host) *\.b\.com
path_beg
path_end
path_reg
url_beg
url
acl实现动静分离示例
acl acl_static path_beg /static /image
acl acl_static path_end .gif .png
acl acl_dynamic path_end .php .jsp
acl acl_b hdr(host) -i www.b.com
use_backend static_group if acl_static
use_backend dynamic_group if acl_dynamic
use_backend b_group if acl_b
定义了三种acl,动态请求、静态请求、请求主机头是www.b.com的,分别将其转发到3个主机组,
之后,定义三个主机组即可