一、负载均衡
为什么使用负载均衡?
- Web服务器的动态水平扩展-->对用户无感知
- 增加业务并发访问及处理能力-->解决单服务器瓶颈问题·
- 节约公网IP地址-->降低IT支出成本
- 隐藏内部服务器IP-->提高内部服务器安全性
- 配置简单-->固定格式的配置文件
- 功能丰富-->支持四层和七层,支持动态下线主机
- 性能较强-->并发数万甚至数十万
四层负载均衡
- 通过ip+port决定负载均衡的去向
- 对流量请求进行NAT处理,转发至后台服务器
- 记录tcp、udp流量分别是由哪台服务器处理,后续该请求连接的流量都通过该服务器处理
- 支持四层的软件:lvs 重量级四层负载均衡器(LVS只做流量传输)
- 客户端和RS之间也是有网络连接的
七层负载均衡
通过虚拟ur|或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡。
代理后台服务器与客户端建立连接,如nginx可代理前后端,与前端客户端tcp连接,与后端服务器
- 建立tcp连接
- 支持7层代理的软件:
- Nginx:基于http协议(nginx七层是通过proxy_pass).
- Haproxy:七层代理,会话保持、标记、路径转移等。
- Nginx:轻量级四层负载均衡器,可缓存(nginx四层是通过upstream模块)
- Haproxy:模拟四层转发
四层和七层的区别
主要的区别就是在对后台的服务器进行负载均衡的时候,依据四层的信息还是七层的信息来决定怎么转发流量
四层:通过发布三层的IP地址(MIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理
七层:就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡
- 分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下
- 性能:四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高;七层可支持解析应用层报文消息内容,识别URL、Cookie、HTTP header等信息。
- 原理:四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等。
- 功能类比:四层负载均衡类似于路由器;七层类似于代理服务器。
- 安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击
二.haproxy简介

实验环境







三、haproxy的基本配置信息
HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:
- 进程及安全配置相关的参数
- 性能调整相关参数
- Debug参数
- defaults:为frontend, backend, listen提供默认配置
- frontend:前端,相当于nginx中的server {}
- backend:后端,相当于nginx中的upstream {}
- listen:同时拥有前端和后端配置,配置简单,生产推荐使用

多进程和线程
启动多线程
注意:多线程和多进程之间不能同时使用会互斥








disabled ----代表下线了
redirect prefix http://www.baidu.com/ ---重定向网页
maxconn <maxconn>
socat工具

haproxy多进程如何热处理
stdio标准的输入输出

四、haproxy的算法
静态算法
static-rr:
- 基于权重的轮询调度
- 不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)
- 不支持端服务器慢启动(慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分)
first
- 根据服务器在列表中的位置,自上而下进行调度
- 其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务
- 其会忽略服务器的权重设置
- 不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效
动态算法
- 基于后端服务器状态进行调度适当调整,
- 新请求将优先调度至当前负载较低的服务器
- 权重可以在haproxy运行时动态调整无需重启
roundrobin(最广泛也是默认使用的)
- 基于权重的轮询动态调度算法,
- 支持权重的运行时调整,不同于lvs中的rr轮训模式,
- HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),
- 其每个后端backend中最多支持4095个real server
- 支持对real server权重动态调整
- roundrobin为默认调度算法,此算法使用广泛
leastconn
- leastconn加权的最少连接的动态
- 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
- 比较适合长连接的场景使用,比如:MySQL等场景
其他算法
source
源地址 hash ,基于用户源地址 hash 并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web 服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type 支持的选项更改这个算法一般是在不插入 Cookie 的 TCP模式下使用,也可给拒绝会话cookie 的客户提供最好的会话粘性,适用于 session 会话保持但不支持cookie和缓存的场景源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash
map-base 取模法(静态)
取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变
一致性hash(动态)
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动 hash( o ) mod n。该 hash 算法是动态的,支持使用 socat 等工具进行在线权重调整,支持慢启动
uri
- 基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后
- 根据最终结果将请求转发到后端指定服务器
- 适用于后端是缓存服务器场景
- 默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性
url_param
- url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器,后端搜索同一个数据会被调度到同一个服务器,多与电商
- 通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server
- 如果无没key,将按roundrobin算法.
hdr
- 针对用户每个http头部(header)请求中的指定信息做hash,
- 此处由 name 指定的http首部将会被取出并做hash计算,
- 然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。
算法总结
#静态static-rr--------->tcp/http
first------------->tcp/http
#动态
roundrobin-------->tcp/http
leastconn--------->tcp/http
random------------>tcp/http
#以下静态和动态取决于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http
算法使用场景
first #使用较少static-rr #做了session共享的web集群
roundrobin
random
leastconn #数据库
source
#基于客户端公网IP的会话保持
Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http #可以实现session保持
hdr #基于客户端请求报文头部做下一步处理
————————————————
五、 高级功能及配置
基于cookie的会话保持
为当前 server 指定 cookie 值,实现基于 cookie 的会话黏性,相对于基于 source 地址 hash
调度算法对客户端的粒度更精准,但同时也加大了 haproxy 负载,目前此模式使用较少, 已经被 session共享服务器代替
不支持 mode tcp ,使用 mode http
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [ preserve ][httponly] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]
name: #cookie 的 key 名称,用于实现持久连接
insert: #插入新的 cookie, 默认不插入 cookie
indirect: #如果客户端已经有 cookie, 则不会再发送 cookie 信息
nocache :
#当 client 和 hapoxy 之间有缓存服务器(如: CDN )时,不允许中间缓存器缓存 cookie ,
#因为这会导致很多经过同一个 CDN 的请求都发送到同一台后端服务器
IP透传
web 服务器中需要记录客户端的真实 IP 地址,用于做访问统计、安全防护、行为分析、区域排行等场景
七层IP透传
当haproxy工作在七层的时候,也可以透传客户端真实IP至后端服务器
四层IP透传
ACL
是一种基于包过滤的访问控制技术
它可以根据设定的条件对经过服务器传输的数据包进行过滤 ( 条件匹配 ) 即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL 、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。
ACL配置选项
# 用 acl 来定义或声明一个 acl
acl <aclname> <criterion> [flags] [operator] [<value>]
acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型
acl test path_end -m sub /a
ACL-criterion 匹配规范
hdr string ,提取在一个 HTTP 请求报文的首部
hdr ( [<name> [ , <occ>]] ):完全匹配字符串 ,header 的指定信息, <occ> 表示在多值中使用的值的出现次数
hdr_beg ( [<name> [ , <occ>]] ):前缀匹配, header 中指定匹配内容的 begin
hdr_end ( [<name> [ , <occ>]] ):后缀匹配, header 中指定匹配内容 end
hdr_dom ( [<name> [ , <occ>]] ):域匹配, header 中的 dom ( host )
hdr_dir ( [<name> [ , <occ>]] ):路径匹配, header 的 uri 路径
hdr_len ( [<name> [ , <occ>]] ):长度匹配, header 的长度匹配
hdr_reg ( [<name> [ , <occ>]] ):正则表达式匹配,自定义表达式 (regex) 模糊匹配
hdr_sub ( [<name> [ , <occ>]] ):子串匹配, header 中的 uri 模糊匹配 模糊匹配 c 报文中 a/b/c 也会匹配
# 示例:
hdr(<string>) 用于测试请求头部首部指定内容
hdr_dom(host) 请求的 host 名称,如 www.timinglee.org
hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp.
hdr_end(host) 请求的 host结尾,如 .com .net .cn
# 示例:
acl bad_agent hdr_sub(User-Agent) -i curl wget
http-request deny if bad_agent
# 有些功能是类似的,比如以下几个都是匹配用户请求报文中 host 的开头是不是 www
acl short_form hdr_beg(host) www.
acl alternate1 hdr_beg(host) -m beg www.
acl alternate2 hdr_dom(host) -m beg www.
acl alternate3 hdr(host) -m beg www.
base : string
# 返回第一个主机头和请求的路径部分的连接,该请求从主机名开始,并在问号之前结束 , 对虚拟主机有用
<scheme>://<user>:<password>@ #<host>:<port>/<path>;<params>#?<query>#<frag>
base : exact string match
base_beg : prefix match
base_dir : subdir match
base_dom : domain match
base_end : suffix match
base_len : length match
base_reg : regex match
base_sub : substring match
path : string
# 提取请求的 URL 路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)
<scheme>://<user>:<password>@<host>:<port> #/<path>;<params>#?<query>#<frag>
path : exact string match
path_beg : prefix match # 请求的 URL 开头,如 /static 、 /images 、 /img 、 /css
path_end : suffix match # 请求的 URL 中资源的结尾,如 .gif .png .css .js .jpg .jpeg
path_dom : domain match
path_dir : subdir match
path_len : length match
ACL 匹配模式
path_reg : regex match
path_sub : substring match
# 示例:
path_beg -i /haproxy-status/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg $
path_sub image
path_dir jpegs
path_dom timinglee
url : string
# 提取请求中的整个 URL 。
url : exact string match
url_beg : prefix match
url_dir : subdir match
url_dom : domain match
url_end : suffix match
url_len : length match
url_reg : regex match
url_sub : substring match
dst # 目标 IP
dst_port # 目标 PORT
src # 源 IP
src_port # 源 PORT
# 示例:
acl invalid_src src 10 .0.0.7 192 .168.1.0/24
acl invalid_src src 172 .16.0.0/24
acl invalid_port src_port 0 :1023
status : integer # 返回在响应报文中的状态码
# 七层协议
acl valid_method method GET HEAD
http-request deny if! valid_method