环境
CentOS Linux release 7.9.2009 (Core)
HAProxy version 2.3.6-7851701, released 2021/03/03
IP: 192.168.0.1
Docker 安装
建立haproxy配置文件
# 新建目录
mkdir -p /etc/haproxy
# 备份配置文件
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.`date +%Y%m%d_%H%M%S`
# 写入配置文件
cat << \EOF > /etc/haproxy/haproxy.cfg
global # 全局参数配置
daemon # 后台运行
nbthread 16 # 线程数,新版本已抛弃nbproc参数
log 127.0.0.1 local3 info # 定义日志分别输出到local3、4
log 127.0.0.1 local4 warning # 日志级别不同
defaults # 默认参数配置
mode tcp # 代理模式tcp、http
retries 3 # 检测次数
maxconn 32768 # 每一个代理的最大连接数
timeout connect 5s # 成功连接到一台服务器的最长等待时间
timeout client 5s # 连接客户端发送数据时的成功连接最长等待时间
timeout server 5s # 服务器端回应客户度数据发送的最长等待时间
listen proxy01 # 代理01,名字自定义
bind *:5000 # 侦听IP和端口,单一IP或多个,0.0.0.0:5000 | 192.168.0.1:5000
mode http # 代理模式,覆盖了上面默认配置
balance roundrobin # 负载均衡方式,轮询
option httplog # 日志记录HTTP请求
option dontlognull # 日志中将不会记录空连接
option forwardfor # 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP
http-request set-header Host www.examplesite.com # 设定头,有时候后端服务器需要,不需要可不设置
# HAProxy持久连接方式,最后说明
option http-server-close
option http-pretend-keepalive
# 日志格式
#log-format %ci:%cp\ %si:%sp\ %B\ %U\ %ST\ %r\ %b\ %f\ %bi\ %hrl\ %hsl\
log-format {"haproxy_clientIP":"%ci","haproxy_clientPort":"%cp","haproxy_dateTime":"%t","haproxy_frontendNameTransport":"%ft","haproxy_backend":"%b","haproxy_serverName":"%s","haproxy_Tw":"%Tw","haproxy_Tc":"%Tc","haproxy_Tt":"%Tt","haproxy_bytesRead":"%B","haproxy_terminationState":"%ts","haproxy_actconn":%ac,"haproxy_FrontendCurrentConn":%fc,"haproxy_backendCurrentConn":%bc,"haproxy_serverConcurrentConn":%sc,"haproxy_retries":%rc,"haproxy_srvQueue":%sq,"haproxy_backendQueue":%bq,"haproxy_backendSourceIP":"%bi","haproxy_backendSourcePort":"%bp"}
option httpchk GET /test/index.php # 检测后端服务器页面判断健康,默认是检测端口
# 后端服务器
server website01 192.168.1.10:80 weight 1 maxconn 10000 check inter 10s
server website02 192.168.1.20:80 weight 1 maxconn 10000 check inter 10s
#server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup
# server语法:server [:port] [param*]
# 使用server关键字来设置后端服务器;为后端服务器所设置的内部名称[php_server_1],该名
#称将会呈现在日志或警报中、后端服务器的IP地址,支持端口映射[10.12.25.68:80]、指定该
#服务器的SERVERID为1[cookie 1]、接受健康监测[check]、监测的间隔时长,单位毫秒[inter
#2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端
#服务器是不可用的[fall 3]、分发的权重[weight 2]、最为备份用的后端服务器,当正常的服
#务器全部都宕机后,才会启用备份服务器[backup]
listen proxy02 # 代理02,名字自定义
bind 192.168.0.1:10881
mode tcp # 四层代理
balance leastconn # 负载均衡方式,见最后说明
log-format {"haproxy_clientIP":"%ci","haproxy_clientPort":"%cp","haproxy_dateTime":"%t","haproxy_frontendNameTransport":"%ft","haproxy_backend":"%b","haproxy_serverName":"%s","haproxy_Tw":"%Tw","haproxy_Tc":"%Tc","haproxy_Tt":"%Tt","haproxy_bytesRead":"%B","haproxy_terminationState":"%ts","haproxy_actconn":%ac,"haproxy_FrontendCurrentConn":%fc,"haproxy_backendCurrentConn":%bc,"haproxy_serverConcurrentConn":%sc,"haproxy_retries":%rc,"haproxy_srvQueue":%sq,"haproxy_backendQueue":%bq,"haproxy_backendSourceIP":"%bi","haproxy_backendSourcePort":"%bp"}
server server1 192.168.2.10:10000 weight 1 maxconn 10000 check inter 5s
server server2 192.168.2.20:10000 weight 1 maxconn 10000 check inter 5s
listen admin_stats # 状态页
bind *:1080
bind-process 1 # 状态页进程数,默认会有警告
mode http
option httplog
option dontlognull
log-format {"haproxy_clientIP":"%ci","haproxy_clientPort":"%cp","haproxy_dateTime":"%t","haproxy_frontendNameTransport":"%ft","haproxy_backend":"%b","haproxy_serverName":"%s","haproxy_Tw":"%Tw","haproxy_Tc":"%Tc","haproxy_Tt":"%Tt","haproxy_bytesRead":"%B","haproxy_terminationState":"%ts","haproxy_actconn":%ac,"haproxy_FrontendCurrentConn":%fc,"haproxy_backendCurrentConn":%bc,"haproxy_serverConcurrentConn":%sc,"haproxy_retries":%rc,"haproxy_srvQueue":%sq,"haproxy_backendQueue":%bq,"haproxy_backendSourceIP":"%bi","haproxy_backendSourcePort":"%bp"}
maxconn 10 # 状态页的最大连接数
stats refresh 30s # 刷新时间
stats uri /hastats # 状态页位置 uri
stats realm XXX-XXX # 登录框提示
stats auth admin:qR49cRBNY5H # 登录信息
stats hide-version # 隐藏状态页的版本信息,显示有安全风险
EOF
rsyslog日志配置
# 配置haproxy日志
# 配置文件生效参数 UDP 接收日志数据 /etc/rsyslog.conf
# $ModLoad imudp
# $UDPServerRun 514
# 替换Rsyslog配置文件注释掉的参数
sed -i 's/\#$ModLoad imudp/$ModLoad imudp/' /etc/rsyslog.conf
sed -i 's/\#$UDPServerRun 514/$UDPServerRun 514/' /etc/rsyslog.conf
# 在local3收info的日志写入文件
echo "local3.* /var/log/haproxy.log" >> /etc/rsyslog.conf
# 在local4收warning的日志写入文件
echo "local4.* /var/log/haproxy_warning.log" >> /etc/rsyslog.conf
systemctl restart rsyslog
日志切割神器 logrotate
# 这个配置将会每天转储/var/log/haproxy.log文件
# /etc/logrotate.conf 配置文件有 include /etc/logrotate.d
# 在/etc/logrotate.d下面写入一个配置文件
cat << \EOF > /etc/logrotate.d/haproxy
/var/log/haproxy.log { # 处理的日志文件
missingok # 在日志轮循期间,任何错误将被忽略,例如 “文件无法找到” 之类的错误
daily # 每日
compress # 压缩
minsize 10M # 最小size
rotate 7 # 保留份数
notifempty # 如果是空文件的话,不转储
dateext # 转储文件加日期,效果:haproxy.log-20210320.gz
}
EOF
# 同上,处理warning日志
cat << \EOF > /etc/logrotate.d/haproxy_warning
/var/log/haproxy_warning.log {
missingok
daily
compress
minsize 10M
rotate 7
notifempty
dateext
}
EOF
Docker运行
docker pull haproxy
docker run -d -it --name haproxy --restart=always \
--net=host --log-opt max-size=50m --log-opt max-file=10\
-v /etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \ # 映射配置文件
-v /etc/localtime:/etc/localtime \ # 同步容器时间
haproxy:latest
操作系统优化
# 操作系统参数优化
cat << \EOF >> /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.ip_local_port_range="1024 65024"
net.ipv4.tcp_max_syn_backlog=100000
net.core.netdev_max_backlog=100000
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout = 10
fs.file-max=500000
EOF
echo '* - nofile 500000' >> /etc/security/limits.conf
负载均衡方式
balance url_param [check_post]
定义后端使用的负载算法。可用区域:
defaults | frontend | listen | backend
yes | no | yes | yes
.
1、 roundrobin:表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法。该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
2、static-rr:每个服务器根据权重轮流使用,类似roundrobin,但它是静态的,意味着运行时修改权限是无效的。另外,它对服务器的数量没有限制。该算法一般不用;
3、first:可用连接槽的第一个服务器接收连接。并且在第一个服务器恢复之后,能够主动切回来,对于MySQL主主代理来说,绝对是一个福音。
4、 leastconn:连接数最少的服务器优先接收连接。leastconn建议用于长会话服务,例如LDAP、SQL、TSE等,而不适合短会话协议。如HTTP.该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
5、source:对请求源IP地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个客户端IP地址总是访问同一个服务器。如果哈希的结果随可用服务器数量而变化,那么客户端会定向到不同的服务器;该算法一般用于不能插入cookie的Tcp模式。它还可以用于广域网上为拒绝使用会话cookie的客户端提供最有效的粘连;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
6、uri:表示根据请求的URI左端(问号之前)进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个URI地址总是访问同一个服务器。一般用于代理缓存和反病毒代理,以最大限度的提高缓存的命中率。该算法只能用于HTTP后端;该算法一般用于后端是缓存服务器;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
7、url_param:在HTTP GET请求的查询串中查找中指定的URL参数,基本上可以锁定使用特制的URL到特定的负载均衡器节点的要求;该算法一般用于将同一个用户的信息发送到同一个后端服务器;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
8、hdr(name):在每个HTTP请求中查找HTTP头,HTTP头将被看作在每个HTTP请求,并针对特定的节点;如果缺少头或者头没有任何值,则用roundrobin代替;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
9、rdp-cookie(name):为每个进来的TCP请求查询并哈希RDP cookie;该机制用于退化的持久模式,可以使同一个用户或者同一个会话ID总是发送给同一台服务器。如果没有cookie,则使用roundrobin算法代替;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
HAProxy持久连接方面的参数
By default HAProxy operates in a tunnel-like mode with regards to persistent connections: for each connection it processes the first request and forwards everything else (including additional requests) to selected server.
Once established, the connection is persisted both on the client and server sides.
Use “option http-server-close” to preserve client persistent connections while handling every incoming request individually, dispatching them one after another to servers, in HTTP close mode.
Use “option httpclose” to switch both sides to HTTP close mode.
“option forceclose” and “option http-pretend-keepalive” help working around servers misbehaving in HTTP close mode.
默认情况下,HAProxy在持久连接方面以类似于隧道的模式运行:对于每个连接,HAProxy处理第一个请求并将其他所有内容(包括其他请求)转发到选定的服务器。
建立后,连接将在客户端和服务器端均保持不变。
使用“选项http-server-close”可保留客户端持久连接,同时分别处理每个传入请求,并以HTTP关闭模式将它们一个接一个地分派给服务器。
使用“ option httpclose”将双方都切换到HTTP关闭模式。
“ option forceclose”和“ option http-pretend-keepalive”有助于解决在HTTP关闭模式下行为异常的服务器。
logrotate
logrotate 是一个 linux 系统日志的管理工具。可以对单个日志文件或者某个目录下的文件按时间 / 大小进行切割,压缩操作;指定日志保存数量;还可以在切割之后运行自定义命令。
logrotate 是基于 crontab 运行的,所以这个时间点是由 crontab 控制的,具体可以查询 crontab 的配置文件 /etc/anacrontab。 系统会按照计划的频率运行 logrotate,通常是每天。在大多数的 Linux 发行版本上,计划每天运行的脚本位于 /etc/cron.daily/logrotate。
主流 Linux 发行版上都默认安装有 logrotate 包,如果你的 linux 系统中找不到 logrotate, 可以使用 apt-get 或 yum 命令来安装。
执行文件: /usr/sbin/logrotate
主配置文件: /etc/logrotate.conf
自定义配置文件: /etc/logrotate.d/*.conf
修改配置文件后,并不需要重启服务。
由于 logrotate 实际上只是一个可执行文件,不是以 daemon 运行。
常见参数
daily :指定转储周期为每天
weekly :指定转储周期为每周
monthly :指定转储周期为每月
rotate count :指定日志文件删除之前转储的次数,0 指没有备份,5 指保留 5 个备份
tabooext [+] list:让 logrotate 不转储指定扩展名的文件,缺省的扩展名是:.rpm-orig, .rpmsave, v, 和~
missingok:在日志轮循期间,任何错误将被忽略,例如 “文件无法找到” 之类的错误。
size size:当日志文件到达指定的大小时才转储,bytes (缺省) 及 KB (sizek) 或 MB (sizem)
compress: 通过 gzip 压缩转储以后的日志
nocompress: 不压缩
copytruncate:用于还在打开中的日志文件,把当前日志备份并截断
nocopytruncate: 备份日志文件但是不截断
create mode owner group : 转储文件,使用指定的文件模式创建新的日志文件
nocreate: 不建立新的日志文件
delaycompress: 和 compress 一起使用时,转储的日志文件到下一次转储时才压缩
nodelaycompress: 覆盖 delaycompress 选项,转储同时压缩。
errors address : 专储时的错误信息发送到指定的 Email 地址
ifempty :即使是空文件也转储,这个是 logrotate 的缺省选项。
notifempty :如果是空文件的话,不转储
mail address : 把转储的日志文件发送到指定的 E-mail 地址
nomail : 转储时不发送日志文件
olddir directory:储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统
noolddir: 转储后的日志文件和当前日志文件放在同一个目录下
prerotate/endscript: 在转储以前需要执行的命令可以放入这个对,这两个关键字必须单独成行
参考资料
blog.csdn.net/vanexph/art…
github.com/kunpengcomp…
blog.51cto.com/liuzhengwei…
blog.51cto.com/leejia/1421…
www.haproxy.org/download/1.…
wsgzao.github.io/post/logrot…