云原生(Haproxy算法实验)
·
算法简介
一、算法分类与核心概念铺垫
在讲解具体算法前,先明确 HAProxy 算法的核心分类逻辑:
- 静态算法:仅依赖配置文件中的后端服务器权重,运行过程中不动态调整,不考虑服务器的实时状态(如连接数、负载)。
- 动态算法:会实时监控后端服务器的状态(如当前连接数),并根据实时状态动态调整请求分发策略。
- 混合算法:结合 “静态规则” 和 “请求特征”(如客户端 IP、请求 URI)进行分发,部分场景下也会参考服务器实时状态。
二、各类算法详细解析
1. 静态算法
(1)static-rr(静态轮询)
- 核心原理:完全按照配置的服务器权重,循环分发请求,运行过程中不调整权重,也不感知服务器的在线 / 离线状态(即使某台服务器宕机,仍会尝试分发请求)。
- 权重规则:比如后端有两台服务器,server1 weight 2,server2 weight 1,则分发顺序为 server1 → server1 → server2 → server1 → server1 → server2... 严格按权重比例循环。
- 配置示例:
backend web_servers balance static-rr # 指定静态轮询算法 server s1 192.168.1.10:80 weight 2 check server s2 192.168.1.11:80 weight 1 check - 适用场景:服务器性能完全一致、且能确保所有服务器始终在线的场景(如静态资源服务器集群);不推荐在生产环境单独使用(无故障自动规避)。
(2)first(优先分发)
- 核心原理:优先将所有请求分发到列表中第一台可用服务器,只有当第一台服务器不可用时,才会分发到第二台,以此类推。权重对该算法无效。
- 工作特点:极端的 “独占式” 分发,第一台服务器会承接所有流量,直到其不可用。
- 配置示例:
backend web_servers balance first # 指定优先分发算法 server s1 192.168.1.10:80 check # 优先分发到s1 server s2 192.168.1.11:80 check # s1不可用时才用s2 - 适用场景:灾备场景(主服务器承接所有流量,备服务器仅在主服务器故障时启用);测试环境(优先使用某台服务器,其他作为备用)。
2. 动态算法
(1)roundrobin(动态轮询,默认算法)
- 核心原理:基础逻辑是轮询,但会动态感知服务器状态(通过 check 检测),自动跳过不可用服务器;同时支持运行时调整权重(无需重启 HAProxy)。
- 权重规则:和 static-rr 类似,但权重可动态修改(如通过
echo "set weight web_servers/s1 3" | socat stdio /var/run/haproxy.sock调整)。 - 配置示例:
backend web_servers balance roundrobin # 默认算法,可省略 server s1 192.168.1.10:80 weight 2 check server s2 192.168.1.11:80 weight 1 check server s3 192.168.1.12:80 weight 1 check - 适用场景:绝大多数通用场景,尤其是后端服务器性能接近、请求处理时间短且均匀的场景(如普通 Web 服务)。
(2)leastconn(最小连接数)
- 核心原理:优先将请求分发到当前活跃连接数最少的服务器,会动态计算各服务器的连接数,兼顾权重(权重越高,可承接的连接数越多)。
- 工作特点:适合长连接场景,能避免某台服务器因连接堆积导致负载过高。
- 配置示例:
backend db_servers balance leastconn # 最小连接数算法 server db1 192.168.1.20:3306 weight 2 check server db2 192.168.1.21:3306 weight 2 check - 适用场景:长连接服务(如数据库、RPC 服务、WebSocket);请求处理时间差异大的场景(如复杂查询的 API 服务)。
3. 混合算法(基于请求特征的哈希算法)
这类算法的核心是对请求特征做哈希计算,将相同特征的请求固定分发到同一台服务器(实现 “会话粘滞”),部分算法可结合动态状态调整。
(1)source(基于客户端 IP 哈希)
- 核心原理:对客户端 IP 地址做哈希计算,将同一 IP 的所有请求分发到同一台服务器;支持
hash-type(如 modular、consistent),可结合权重。 - 工作特点:实现简单的会话粘滞,无需额外存储会话信息;但如果客户端是 NAT 网关后的集群(如同一公司所有员工共用一个公网 IP),会导致请求集中到某台服务器。
- 配置示例:
backend web_servers balance source # 基于客户端IP哈希 hash-type consistent # 一致性哈希,减少服务器上下线时的分发波动 server s1 192.168.1.10:80 weight 2 check server s2 192.168.1.11:80 weight 1 check - 适用场景:需要简单会话粘滞的场景(如未做会话共享的 Web 应用);客户端 IP 分布均匀的场景。
(2)uri(基于请求 URI 哈希)
- 核心原理:对请求的 URI(如
/index.html、/api/user)做哈希计算,相同 URI 的请求分发到同一台服务器;可指定uri_depth(截取 URI 的前 N 层)。 - 工作特点:适合静态资源服务器集群,能利用服务器缓存(同一静态资源的请求始终到同一台服务器,提升缓存命中率)。
- 配置示例:
backend static_servers balance uri # 基于URI哈希 uri_depth 1 # 仅截取URI的第一层(如/api/user只取/api) server s1 192.168.1.30:80 check server s2 192.168.1.31:80 check - 适用场景:静态资源服务(图片、CSS、JS);CDN 节点分发。
(3)url_param(基于 URL 参数哈希)
- 核心原理:提取 URL 中指定参数的值做哈希,比如指定
userid,则/login?userid=123和/profile?userid=123会分发到同一台服务器。 - 配置示例:
backend app_servers balance url_param userid # 基于userid参数哈希 server s1 192.168.1.40:80 check server s2 192.168.1.41:80 check - 适用场景:需要按业务参数粘滞的场景(如按用户 ID 分发请求,确保同一用户的请求到同一服务器)。
(4)hdr(基于 HTTP 请求头哈希)
- 核心原理:提取指定 HTTP 请求头的值做哈希,比如
hdr(Cookie)(基于 Cookie)、hdr(Host)(基于域名)、hdr(X-Real-IP)(基于真实客户端 IP);如果指定的头不存在,会降级到 roundrobin 算法。 - 配置示例:
backend web_servers balance hdr(Cookie) # 基于Cookie哈希实现会话粘滞 server s1 192.168.1.10:80 check server s2 192.168.1.11:80 check - 适用场景:精准的会话粘滞(如基于 SessionID 的 Cookie);多域名服务(基于 Host 头分发到不同服务器)。
总结
- 静态算法(static-rr、first):仅依赖配置权重,无动态调整,适用于服务器状态稳定的场景(如灾备、静态资源),但故障容错性差。
- 动态算法(roundrobin、leastconn):实时感知服务器状态,roundrobin 适用于短连接通用场景,leastconn 适用于长连接 / 请求耗时不均的场景。
- 混合算法(source、uri、url_param、hdr):基于请求特征哈希实现会话粘滞,分别适用于 IP 粘滞、静态资源缓存、业务参数粘滞、请求头粘滞等场景。
静态算法
1.static-rr
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance static-rr
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
#检测是否支持热更新
[root@haproxy yxs]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
2 (initial 2)
[root@haproxy yxs]# echo "set weight webcluster/haha 1 " | socat stdio /var/lib/haproxy/stats Backend is using a static LB algorithm and only accepts weights '0%' and '100%'
2026/02/08 14:40:05 socat[3172] E exactly 2 addresses required (there are 16); use option "-h" for help
2.first
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
bind *:80
balance first
server haha 192.168.0.10:80 maxconn 1 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试:在一个shell中执行持续访问
[root@test yxs]# while true; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
#在其他设立了中建立持续访问并观察
[root@test2 yxs]# while true; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20 #此处出现20信息
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
动态算法
1.roundrobin
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance roundrobin
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
#动态权重更新
[root@haproxy yxs]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
2 (initial 2)
[root@haproxy yxs]# echo "set weight webcluster/haha 1 " | socat stdio /var/lib/haproxy/stats
[root@haproxy yxs]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
1 (initial 2)
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
2.leastconn
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance leastconn
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
混合算法
1.source
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance source
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
#source动态算法
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance source
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
2.uri
#主备实验环境
[root@webserver1 yxs]# echo RS1 - 192.168.0.10 > /var/www/html/index1.html
[root@webserver1 yxs]# echo RS1 - 192.168.0.10 > /var/www/html/index2.html
[root@webserver2 yxs]# echo RS2 - 192.168.0.20 > /var/www/html/index1.html
[root@webserver2 yxs]# echo RS2 - 192.168.0.20 > /var/www/html/index2.html
#设定uri算法
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance uri
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100/index2.html; done
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
3.url_param
#主备实验环境
[root@webserver1 yxs]# echo RS1 - 192.168.0.10 > /var/www/html/index1.html
[root@webserver1 yxs]# echo RS1 - 192.168.0.10 > /var/www/html/index2.html
[root@webserver2 yxs]# echo RS2 - 192.168.0.20 > /var/www/html/index1.html
[root@webserver2 yxs]# echo RS2 - 192.168.0.20 > /var/www/html/index2.html
#设定url_param算法
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance url_param name
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100/index.html?name=lee; done
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
[root@test yxs]# for i in {1..10}; do curl 172.25.254.100/index.html?name=redhat; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
4.hdr
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance hdr(User-Agent)
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart haproxy.service
#测试
[root@test yxs]# curl -A "lee" 172.25.254.100
webserver2 - 192.168.0.20
[root@test yxs]# curl -A "lee" 172.25.254.100
webserver2 - 192.168.0.20
[root@test yxs]# curl -A "timinglee" 172.25.254.100
webserver2 - 192.168.0.20
[root@test yxs]# curl -A "timing" 172.25.254.100
webserver1 - 192.168.0.10
更多推荐
所有评论(0)