目录
一、haproxy简介
二、haproxy实验
1.环境部署
2.haproxy的基本部署方法及负载均衡的实现
2.1安装软件
2.2haproxy的基本配置
3.haproxy的全局配置参数及日志分离
3.1多线程设定
3.2自定义日志
4.haproxy-proxies中的常用配置参数
4.1设置backup --- sorryserver的端口
4.2访问重定向
5.haproxy热更新方法
5.1socat
6.haproxy中的算法
6.1静态算法
6.1.1static-rr:基于权重的轮询调度
6.1.2 first
6.2动态算法
6.2.1roundrobin
6.2.2 leastconn
6.3其他算法
6.3.1source
6.3.1.1 map-base 取模法
6.3.1.2 一致性hash
6.3.2 uri
6.3.2.1 uri 取模法配置示例
6.3.3 url_param
6.3.3.1 url_param取模法配置示例
6.3.4 hdr
6.3.4.1 hdr取模法配置示例
6.3.6 算法总结
6.3.7 各算法使用场景
三.高级功能及配置
3.1.1 配置选项
编辑
3.2HAProxy状态页
3.2.1 状态页配置项
3.3 IP透传
3.3.2 四层IP透传
3.3.3 七层IP透传
3.4 ACL
基于源IP或子网调度访问
基于浏览器的访问控制
基于文件后缀名实现动静分离
重定向错误文件
3.5 haproxy的四层负载
3.6 haproxy中https实现
3.6.1 证书制作
一、haproxy简介
二、haproxy实验
1.环境部署
haproxy | 192.168.5.100 |
webserver1 | 192.168.5.10 |
webserver2 | 192.168.5.20 |
2.haproxy的基本部署方法及负载均衡的实现
2.1安装软件
dnf install haproxy -y
2.2haproxy的基本配置
3.haproxy的全局配置参数及日志分离
3.1多线程设定
3.2自定义日志
vim /etc/rsyslog.conf
4.haproxy-proxies中的常用配置参数
4.1设置backup --- sorryserver的端口
disabled指定下线的后端服务器
4.2访问重定向
5.haproxy热更新方法
5.1socat
下载
dnf install socat -y
# 查看 haproxy 状态[root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats
# 查看集群状态[root@haproxy ~]# echo "show servers state" | socat stdio /var/lib/haproxy/stats
# 查看集群权重[root@haproxy ~]# echo get weight webcluster/web1 | socat stdio /var/lib/haproxy/stats2 (initial 2)[root@haproxy ~]# echo get weight webcluster/web2 | socat stdio /var/lib/haproxy/stats1 (initial 1)
# 设置权重[root@haproxy ~]# echo "set weight webcluster/web1 1 " | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# echo "set weight webcluster/web1 2 " | socat stdio /var/lib/haproxy/stats
# 下线后端服务器[root@haproxy ~]# echo "disable server webcluster/web1 " | socat stdio/var/lib/haproxy/stats
# 上线后端服务器[root@haproxy ~]# echo "enable server webcluster/web1 " | socat stdio /var/lib/haproxy/stats
6.haproxy中的算法
6.1静态算法
6.1.1static-rr:基于权重的轮询调度
6.1.2 first
# 在两台主机上分别执行此循环,可以观察是否 102 被调度到while true;do curl 172.25.254.100 ; sleep 0.1;done
6.2动态算法
6.2.1roundrobin
[root@haproxy ~]# echo "set weight webserver_80/webserver1 2" | socat stdio/var/lib/haproxy/haproxy.sock
6.2.2 leastconn
6.3其他算法
6.3.1source
6.3.1.1 map-base 取模法
比如当源 hash 值时 1111 , 1112 , 1113 ,三台服务器 a b c 的权重均为 1 ,即 abc 的调度标签分别会被设定为 0 1 2 ( 1111%3=1 , 1112%3=2 , 1113%3=0 )1111 ----- > nodeb1112 ------> nodec1113 ------> nodea如果 a 下线后,权重数量发生变化1111%2=1 , 1112%2=0 , 1113%2=11112 和 1113 被调度到的主机都发生变化,这样会导致会话丢失
# 不支持动态调整权重值[root@haproxy ~]# echo "set weight webserver_80/webserver1 2" | socat stdio/var/lib/haproxy/haproxy.sockBackend is using a static LB algorithm and only accepts weights '0%' and '100%'.# 只能动态上线和下线[root@haproxy ~]# echo "set weight webserver_80/webserver1 0" | socat stdio/var/lib/haproxy/haproxy.sock[root@haproxy ~]# echo "get weight webserver_80/webserver1" | socat stdio/var/lib/haproxy/haproxy.sock0 (initial 1)
6.3.1.2 一致性hash
1 、后端服务器哈希环点 keyA=hash( 后端服务器虚拟 ip)%(2^32)2 、客户机哈希环点 key1=hash(client_ip)%(2^32) 得到的值在 [0---4294967295] 之间,3 、将 keyA 和 key1 都放在 hash 环上,将用户请求调度到离 key1 最近的 keyA 对应的后端服务器
增加虚拟服务器 IP 数量,比如:一个后端服务器根据权重为 1 生成 1000 个虚拟 IP ,再 hash 。而后端服务器权 重为2 则生成 2000 的虚拟 IP ,再 bash, 最终在 hash 环上生成 3000 个节点,从而解决 hash 环偏斜问题
6.3.2 uri
注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>左半部分: /<path>;<params>整个 uri : /<path>;<params>?<query>#<frag>
6.3.2.1 uri 取模法配置示例
6.3.3 url_param
# 假设:url = http://www.timinglee.com/foo/bar/index.php?key=value# 则:host = "www.timinglee.com"url_param = "key=value"
6.3.3.1 url_param取模法配置示例
6.3.4 hdr
6.3.4.1 hdr取模法配置示例
6.3.6 算法总结
# 静态static-rr--------->tcp/httpfirst------------->tcp/http# 动态roundrobin-------->tcp/httpleastconn--------->tcp/http# 以下静态和动态取决于 hash_type 是否 consistentsource------------>tcp/httpUri--------------->httpurl_param--------->httphdr--------------->http
6.3.7 各算法使用场景
first # 使用较少static-rr # 做了 session 共享的 web 集群roundrobinleastconn # 数据库source# 基于客户端公网 IP 的会话保持Uri--------------->http # 缓存服务器, CDN 服务商,蓝汛、百度、阿里云、腾讯url_param--------->http # 可以实现 session 保持hdr # 基于客户端请求报文头部做下一步处理
三.高级功能及配置
3.1基于cookie的会话保持
3.1.1 配置选项
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]name : #cookie 的 key 名称,用于实现持久连接insert : # 插入新的 cookie, 默认不插入 cookieindirect : # 如果客户端已经有 cookie, 则不会再发送 cookie 信息nocache : # 当 client 和 hapoxy 之间有缓存服务器(如: CDN )时,不允许中间缓存器缓存 cookie ,# 因为这会导致很多经过同一个 CDN 的请求都发送到同一台后端服务器
3.2HAProxy状态页
3.2.1 状态页配置项
stats enable # 基于默认的参数启用 stats pagestats hide-version # 将状态页中 haproxy 版本隐藏stats refresh <delay> # 设定自动刷新时间间隔,默认不自动刷新stats uri <prefix> # 自定义 stats page uri ,默认值: /haproxy?statsstats auth <user>:<passwd> # 认证时的账号和密码,可定义多个用户 , 每行指定一个用户# 默认: no authenticationstats admin { if | unless } <cond> # 启用 stats page 中的管理功能
#pid 为当前 pid 号, process 为当前进程号, nbproc 和 nbthread 为一共多少进程和每个进程多少个线程pid = 27134 (process #1, nbproc = 1, nbthread = 1)# 启动了多长时间uptime = 0d 0h00m04s# 系统资源限制:内存 / 最大打开文件数 /system limits: memmax = unlimited; ulimit-n = 200029# 最大 socket 连接数 / 单进程最大连接数 / 最大管道数 maxpipesmaxsock = 200029; maxconn = 100000; maxpipes = 0# 当前连接数 / 当前管道数 / 当前连接速率current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000 kbps# 运行的任务 / 当前空闲率Running tasks: 1/14; idle = 100 %active UP : # 在线服务器backup UP : # 标记为 backup 的服务器active UP, going down : # 监测未通过正在进入 down 过程backup UP, going down : # 备份服务器正在进入 down 过程active DOWN, going up : #down 的服务器正在进入 up 过程backup DOWN, going up : # 备份服务器正在进入 up 过程active or backup DOWN : # 在线的服务器或者是 backup 的服务器已经转换成了 down 状态not checked : # 标记为不监测的服务器#active 或者 backup 服务器人为下线的active or backup DOWN for maintenance (MAINT)#active 或者 backup 被人为软下线 ( 人为将 weight 改成 0)active or backup SOFT STOPPED for maintenance
3.3 IP透传
3.3.2 四层IP透传
# 查看日志内容[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log192.168.0.10 - - [10/Jul/2024:15:21:00 +0800] "GET / HTTP/1.1"200 18 "-""curl/7.29.0" "-"192.168.0.10 - - [10/Jul/2024:15:26:11 +0800] "GET / HTTP/1.1"200 18 "-""curl/7.29.0" "-"192.168.0.10 - - [10/Jul/2024:15:41:56 +0800] "GET / HTTP/1.1" "172.25.254.10"20018 "-" "curl/7.29.0"
3.3.3 七层IP透传
#apache 配置:
LogFormat "%{X-Forwarded-For}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%
{User-Agent}i\"" combined
#nginx 日志格式:
$proxy_add_x_forwarded_for: 包括客户端IP和中间经过的所有代理的IP
$http_x_forwarded_For: 只有客户端IP
log_format main '"$proxy_add_x_forwarded_for" - $remote_user [$time_local]
"$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_For';
#查看日志如下:
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
"172.25.254.10, 192.168.0.10" 192.168.0.10 - - [10/Jul/2024:16:15:00 +0800] "GET
/ HTTP/1.1"200 18 "-" "curl/7.29.0" "172.25.254.10"
[root@rs2 ~]# tail -n 3 /etc/httpd/logs/access_log
172.25.254.10 192.168.0.10 - - [11/Jul/2024:00:15:00 +0800] "GET / HTTP/1.1" 200
27 "-" "curl/7.29.0
3.4 ACL
基于源IP或子网调度访问
示例:
vim/etc/haproxy/haproxy.cfgfrontend webclusterbind *:80mode httpacl ctrl_ip src 172.25.254.1 172.25.254.20 192.168.0.0/24 -----符合条件的访问RS1use_backend webcluster-host if ctrl_ipdefault_backend default-hostbackend webcluster-hostmode httpserver web1 172.25.254.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 172.25.254.20:80 check inter 2 fall 2 rise 5
测试:
[root@werserver2 ~]# curl 172.25.254.100
webserver1 - 172.25.254.10[root@haproxy ~]# curl www.test.com
webserver2 - 172.25.254.20
[root@haproxy ~]#
frontend webclusterbind *:80mode httpacl ctrl_ip src 172.25.254.1 172.25.254.20 192.168.0.0/24http-request deny if ctrl_ip ------ 符合条件的拒绝访问default_backend default-hostbackend webcluster-hostmode httpserver web1 172.25.254.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 172.25.254.20:80 check inter 2 fall 2 rise 5
测试:
[root@werserver2 ~]# curl 172.25.254.100
webserver1 - 172.25.254.10
[root@werserver2 ~]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
[root@werserver2 ~]# [root@haproxy ~]# curl www.test.com ---- 默认走RS2,走的default
webserver2 - 172.25.254.20
基于浏览器的访问控制
示例:
vim/etc/haproxy/haproxy.cfgfrontend webclusterbind *:80mode httpacl badwebrowers hdr_sub(User-Agent) -i wgethttp-request deny if badwebrowersdefault_backend default-hostbackend webcluster-hostmode httpserver web1 172.25.254.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 172.25.254.20:80 check inter 2 fall 2 rise 5
基于文件后缀名实现动静分离
RS主机上:
[root@webserver1 ~]# dnf install php -y
[root@webserver1 ~]# systemctl restart nginx.service
[root@webserver1 ~]#
[root@webserver1 ~]# vim /usr/share/nginx/html/index.php
<?php phpinfo();
?>查看是否能访问到php
自定义haproxy的错误界面
两台web服务都给他挂掉
[root@werserver1 ~]# systemctl stop nginx.service
[root@werserver2 ~]# systemctl stop nginx.service此时访问不到
重定向错误文件
3.5 haproxy的四层负载
测试
3.6 haproxy中https实现
#配置HAProxy支持https协议,支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
#指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥
cat demo.key demo.crt > demo.pem
#把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
3.6.1 证书制作
haproxy ~]# mkdir /etc/haproxy/certs/
haproxy ~]# openssl req -newkey rsa:2048 \
-nodes -sha256 –keyout /etc/haproxy/certs/timinglee.org.key \
-x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt
haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webserver
bind *:80
redirect scheme https if !{ ssl_fc }
mode http
use_backend webcluster
frontend webserver-https
bind *:443 ssl crt /etc/haproxy/timinglee.org.pem
mode http
use_backend webcluster
backend webcluster
mode http
balance roundrobin
server web1 172.25.254.200:80 check inter 3s fall 3 rise 5
server web2 172.25.254.201:80 check inter 3s fall 3 rise 5
[root@客户端 ~]#curl -IkL http://172.25.254.100
HTTP/1.1 302 Found
content-length: 0
location: https://www.timinglee.org/
cache-control: no-cache
HTTP/1.1 200 OK
date: Sat, 04 Apr 2020 02:31:31 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Thu, 02 Apr 2020 01:44:13 GMT
etag: "a-5a244f01f8adc"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8
[root@centos6 ~]#curl -Ik https://www.timinglee.org
HTTP/1.1 200 OK
date: Sat, 04 Apr 2020 02:31:50 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Thu, 02 Apr 2020 01:44:28 GMT
etag: "a-5a244f0fd5175"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8