参考文章:
HAProxy 是什么
HAProxy 是基于 TCP、HTTP 协议实现的开源 L4-L7 软件负载均衡器,采用单进程和事件驱动模型实现,具有高可用和反向代理特性,支持双机热备与虚拟主机。目标是支持 10000+ 请求连接,为后端业务服务器集群提供高性能的负载均衡服务。适用于大连接数,要求会话保持,分发复杂的流量负载均衡场景。
- 四层代理:HAProxy 采用 NAT 模式,在客户端和 Real Server 之间双向转发流量
- 七层代理:HAProxy 通过分析、理解、修改应用层协议来实现更加 “智能” 的流量分发。
注:Real Server,实际处理客户端请求的业务服务器。
HAProxy 的核心功能
- 负载均衡: L4 和 L7 两种模式,支持 RR、静态RR、LC、IP Hash、URI Hash、URL_PARAM Hash、HTTP_HEADER Hash 等丰富的负载均衡算法
- 健康检查: 支持 TCP 和 HTTP 两种健康检查方式
- 会话保持: 对于未实现会话共享的应用集群,可以通过 Insert Cookie、Rewrite Cookie、Prefix Cookie、以及上述的多种 Hash 方式实现会话保持
- SSL: HAProxy 可以解析 HTTPS 协议,并能够将请求解密为 HTTP 后向后端传输
- HTTP 请求重写与重定向
- 监控与统计: HAProxy 提供了基于 Web 的统计信息页面,展现健康状态和流量数据。基于此功能,使用者可以开发监控程序来监控 HAProxy 的状态
HAProxy 的关键特性
HAProxy 的性能
- 采用单线程、事件驱动、非阻塞模型,减少上下文切换的消耗,能在1ms内处理数百个请求。并且每个会话只占用数KB的内存。
- 大量精细的性能优化,如O(1)复杂度的事件检查器、延迟更新技术、Single-buffereing、Zero-copy forwarding等等,这些技术使得HAProxy在中等负载下只占用极低的CPU资源。
- HAProxy 大量利用操作系统本身的功能特性,使得其在处理请求时能发挥极高的性能,通常情况下,HAProxy 自身只占用 15% 的处理时间,剩余的85%都是在系统内核层完成的。
- HAProxy 作者在8年前(2009)年使用1.4版本进行了一次测试,单个 HAProxy 进程的处理能力突破了 10万请求/秒,并轻松占满了10Gbps的网络带宽。
会话保持
HAProxy 为来自同一客户端的请求访问实现了三种会话保持方案:
- SOURCE_IP: HAProxy 将客户端的 SOURCE IP 进行 Hash 计算并保存,由此确保相同 IP 访问时被转发到同一台 Real Server 上。
- Cookie: HAProxy 依靠 Real Server 发送给客户端的 Cookie 信息进行会话保持
- Session: HAProxy 保存 Real Server 的 Session 及服务器标识
HAProxy 稳定性
建议以单进程模式运行的程序,HAProxy对稳定性的要求是十分严苛的。按照作者的说法,HAProxy在13年间从未出现过一个会导致其崩溃的BUG,HAProxy一旦成功启动,除非操作系统或硬件故障,否则就不会崩溃。
HAProxy 的大部分工作都是在操作系统内核完成的,所以 HAProxy 的稳定性主要依赖于操作系统,作者建议使用2.6或3.x的Linux内核,对 sysctl 参数进行精细的优化,并且确保主机有足够的内存。这样 HAProxy 就能够持续满负载稳定运行数年之久。
sysctl 的建议配置(并不是万用配置,仍然需要针对具体情况进行更精细的调整,但可以作为首次使用 HAProxy 的初始配置使用):
1
2
3
4
5
6
7net.ipv4.tcp_tw_reuse = 1 # 打开 TIME-WAIT 套接字重用功能,
net.ipv4.ip_local_port_range = 1024 65023 # 配置本地端口范围
net.ipv4.tcp_max_syn_backlog = 10240 # 对于还未获得对方确认的连接请求,可保存在队列中的最大数目
net.ipv4.tcp_max_tw_buckets = 400000 # 设置系统的 TIME_WAIT 的数量,如果超过默认值则会被立即清除
net.ipv4.tcp_max_orphans = 60000 # 表示系统中最多有多少TCP套接字不被关联到任何一个用户文件句柄上。如果超过这里设置的数字,连接就会复位并输出警告信息。这个限制仅仅是为了防止简单的DoS攻击。此值不能太小。
net.ipv4.tcp_synack_retries = 3 # 设置内核放弃连接之前发送SYN+ACK包的数量
net.core.somaxconn = 10000 # 定义系统中每一个端口的最大监听队列的长度,这个是全局的参数健康检查
HAProxy 使用 Health Check 来确定 Backend Real Server 能不能处理分发的客户端请求,这避免了运维人员在 Real Server 不可用时需要人工移除。默认的 Health Check 方法是尝试和 Real Server 建立 TCP 连接,比如:检查 Real Server 是否在预设的 IP:Port 上进行监听。
HAProxy 允许手动配置 Health Check 方法,有 TCP,HTTP,PING 三种方式。
当 Real Server 被检查失败时,HAProxy 会自动禁用它,客户端请求不会分发到该 Real Server,直到它重新激活位置。
HAProxy 配置文件
HAProxy 的配置文件为 /etc/haproxy.cfg,主要由 5 部分组成:
- global: 全局配置参数,属于进程级配置,通常与操作系统配置相关。
- defaults: 默认配置参数,此部分的设置参数值默认会自动被引用到 frontend、backend 和 listen,属于公用的配置参数部分。如果 default 的配置参数与后面几个部分的私有配置参数冲突,则优先私有配置参数。
- frontend(前端): 设置接收客户端请求的前端虚拟节点(LB 服务器),允许根据 ACL 规则直接指定 backend。
- backend(后端): 配置后端服务器集群,也就是一组处理客户端请求的 Real Server。
- listen: 是 frontend 部分和 backend 部分的结合体,在较新版本的版本中 listen section 是可选的。
Haproxy 配置详解
global 部分
通常主要定义全局配置,主要用于定义全局参数,属于进程级的配置,通常和操作系统配置有关
1 | global |
- log: 全局的日志配置,local0是日志设备,info 表示日志级别。其中日志级别有 err、warning、info、debug 四种可选。这个配置表示使用 127.0.0.1 上的 rsyslog 服务中的 local0 日志设备,记录日志等级为 info
log 指定收集哪个机器的 log,log 的收集是通过系统工具来实现的,在 centos6 版本之前以 syslog 来收集日志,6版本变为了 rsysylog。这些都是用于收集系统的日志,local0 指定设备,info 表示输出日志的级别,error 级别是在报错的时候才会输出。info 只要有正常信息都会进行输出,生产环境建议设置 为 notice 级别
- maxconn: 设定每个 haproxy 进程可接受的最大并发连接数,此选项等同于Linux命令行选项
ulimit -n
注意:HAProxy 要求系统的
ulimit -n
参数大于 [maxconn*2+18],在设置较大的 maxconn 时,注意检查并修改ulimit -n
参数
- user/group: 设置运行 haproxy 进程的用户和组,也可使用用户和组的 uid 和 gid 值来替代
- nbproc: 设置 HAProxy 启动时可创建的进程数, 此参数要求将 HAProy 运行模式设置为 “daemon”,默认只启动一个进程。
nbproc: 根据使用经验,该值的设置应该小于服务器的CPU核数。创建多个进程能够减少每个进程的任务队列,但是过多的进程可能会导致进程的崩溃。
这个参数重要,设置 haproxy 启动的进程数。默认值是 1,默认启动一个进程,如果访问量比较大需要将该值增加,这个值大小一般建议设置小于服务器cpu的核数,这个核数是物理核不是逻辑核,如两个4核cpu那就是8个核,也就是这个值最多设置为8,而不是通过超线程来实现。创建过多的进程并不一定会有好的效果,进程数不能太大,也不能太小,最大不要超过cpu核数
- pidfle: 指定 haproxy 进程的pid文件, 启动进程的用户必须有访问此文件的权限
default 部分
用于设置配置默认参数,这些参数可以被用到 frontend,backend,listen 组件。
在此部分中设置的参数值,默认会自动引用到下面的 frontend、backend、listen 部分中。如果某些参数属于公用的配置,只需要在 defaults 部分添加一次即可。而如果frontend、backend、listen 部分也配置了与 defaults 部分一样的参数,defaults 部分参数对应的值自动被覆盖。
1 | defaults |
mode∶ 设置 HAPoy 实例默认的运行模式,有 tcp、http、heath 三个可选值。
- tcp 模式∶ 在此模式下,客户端和服务器端之间将建立一个全双工的连接,不会对七层报文做任何类型的检查,默认为 tcp 模式,经常用于 SSL、SSH、SMTP 等应用。
- http 模式∶ 在此模式下,客户端请求在转发至后端服务器之前将会被深度分析,所有不与 RFC 格式兼容的请求都会被拒绝。
- health模式∶ 目前此模式基本已经废弃,不在多说。
retres∶ 设置连接后端服务器的失败重试次数。连接失败的次数如果超过这里设置的值,HAProy 会将对应的后端服务器标记为不可用。此参数也可在后面 backend 部分进行设置。
#健康检查。3次连接失败就认为服务器不可用,主要通过后面的check检查
- timeout connect∶ haproxy 与后端服务器连接超时时间,如果在同一个局域网可设置较小的时间
- timeout client∶ 与客户端的最长空闲时间, 定义客户端与 haproxy 连接后,数据传输完毕,不再有数据传输,即非活动连接的超时时间
- timeout server∶ 定义 haproxy 与上游服务器非活动连接的超时时间
- timeout http-keep-alive: 使用 keepAlive 连接
frontend 部分
frontend 是在haproxy 1.3 版本以后才引入的一个组件,同时引入的还有 backend 组件。通过引入这些组件,在很大程度上简化了 haproxy 配置文件的复杂性。forntend 可以根据ACL规则直接指定要使用的后端 backend。
这是HAProxy 配置文件的第三部分—fronted部分的配置
1 | frontend http_80_in |
- bind *:81 监听端口,即haproxy提供web服务的端口,和 lvs 的 vip 端口类似
- option httplog∶ 默认情况下 haproxy 不会记录 http 请求的,这不便于 haproxy 出现问题时候的排查与监控,这个就是记录 http 请求的日志,这个参数比较重要建议打开。
- option forwardfor: HAProxy 工作于反向代理模式,其发往服务器的请求中的客户端IP均为 HAProxy 主机的地址而非真正客户端的地址,这会使得服务器端的日志信息记录不了真正的请求来源,“X-Forwarded-For” 首部则可用于解决此问题。HAProxy 可以向每个发往服务器的请求上添加此首部,并以客户端IP为其 value。(记录客户端IP在X-Forwarded-For头域中)如果后端服务器需要获得客户端真实ip需要配置的参数,可以从 Http Header 中获得客户端ip。
- option httpclose: 每次请求完毕后主动关闭http通道,HA-Proxy 不支持 keep-alive 模式
- log global∶ 表示使用全局的日志配置,这里的 “global” 表示引用在 HAPoxy 配置文件 global 部分中定义的 log 选项配置格式
- defaut_backend∶ 指定默认的后端服务器池,也就是指定一组后端真实服务器,而这些真实服务器组将在 backend 段进行定义
backend 部分
backend 用于定义一个名称为 htmpool 的后端服务器组,根据需要可以定义多个
1 | backend httpservers |
option redispatch: 此参数用于cookie保持的环境中。在默认情况下,HAProxy会将其请求的后端服务器的serverID插入cookie中,以保证会话的session持久性。而如果后端服务器出现故障,客户端的cookie是不会刷新的,这就会造成无法访问。此时,如果设置了此参数,就会将客户的请求强制定向到另外一台健康的后端服务器上,以保证服务正常
option abortonclose: 此参数可以在服务器负载很高的情况下,自动结束当前队列中处理时间比较长的连接
balance: 设置负载均衡算法 HAProxy 支持的负载均衡算法
- roundrobin: 基于权重进行轮询调度的算法
- static-rr: 基于权重进行轮询调度的算法,不过此算法为静态算法,在运行时调整其服务器权重不会生效
- source: 基于请求源IP的算法。此算法先对请求的源IP进行HASH运算,然后将结果与后端服务器的权重总数相除后转发至某台匹配的后端服务器。这种方式可以使同一个客户端IP的请求始终转发到某特定的后端服务器
- leastconn: 此算法会将新的连接请求转发到具有最少连接数目的后端服务器。在会话时间较长的场景中推荐使用此算法 ,例如数据库负载均衡
- uri: 此算法会对部分或整个 URI 进行HASH运算,再经过与服务器的总权重相除,最后转发到某台匹配的后端服务器上
- uri_param: 此算法会根据 URL 路径中的参数进行转发,这样可保证在后端真实服务器数据不变时,同一个用户的请求始终分发到同一台机器上
- hdr: 此算法根据HTTP头进行转发,如果指定的HTTP头名称不存在,则使用
roundrobin
算法进行策略转发
cookie SERVERID: 表示允许向 cookie 插入SERVERID,每台服务器的SERVERID可在下面的server关键字中使用cookie关键字定义
option httpchk GET /index.html 心跳检测的文件;
此选项表示启用 HTTP 的服务状态检测功能。HAProxy 作为一款专业的负载均衡器,它支持对 backend 部分指定的后端服务节点的健康检查,以保证在后端 backend 中某个节点不能服务时,把从 frotend 端进来的客户端请求分配至 backend 中其他健康节点上,从而保证整体服务的可用性。
option httpchk 的用法如下:option httpchk <method> <uri> <version>
其中,各个参数的含义如下:
参数 描述 method 表示 HTTP 请求的方式,常用的有 OPTIONS,GET,HEAD 几种方式。一般的健康检查可采用 HEAD 方式进行,而不是 GET,这是因为 HEAD 方式没有数据返回,仅检查 Response 的 HEAD 是不是 200 状态码。因此相对于 GET 来说,HEAD 方式更快,更简单 uri 表示要检测的 URL 地址,通过执行此 URL,可以获取后端服务器的运行状态。在正常的情况下都将返回状态码 200,返回其他状态码均为异常状态 version 指定心跳检测时的 HTTP 的版本号(可选) server http1 192.168.179.103:80 maxconn 2000 cookie server1 weight 1 check inter 3s rise 2 fall 3: 服务器定义,
- cookie server1: 表示 serverid 为 server1,
- check inter 1s: 是检测心跳频率,
- rise 3: 是3次正确认为服务器可用,
- fall 3: 是3次失败认为服务器不可用,
- weight 1: 代表权重
server:这个关键字用来定义多个后端真实服务器,不能用于 defaults 和 frontend 部分。使用格式为:
server <name> <address>[:port] [param*]
其中,每个参数含义如下:参数 描述 name 为后端真实服务器指定一个内部名称,随便定义即可 address 后端真实服务器的 IP 地址 或者主机名 port 指定连接请求发往真实服务器时的目标端口。在未设定时,将使用客户端请求时的同一端口 parameter 为后端服务器设定一系列的参数,可选参数非常的多,这里仅介绍常用的一些参数 - check: 表示启用对此后端服务器执行健康状态检查。 - inter: 设置健康状态检查的时间间隔,单位为毫秒。 - rise: 设置从故障状态转换至正常状态需要成功检查的次数,例如。“rise 2”表示 2 次检查正确就认为此服务器可用。 - fall: 设置后端服务器从正常状态转换为不可用状态需要检查的次数,例如,“fall 3”表示 3 次检查失败就认为此服务器不可用。 - cookie: 为指定的后端服务器设定 cookie 值,此处指定的值将在请求入站时被检查,第一次为此值挑选的后端服务器将在后 - backup: 设置后端真实服务器的备份服务器,仅仅在后端所有真实服务器均不可用的情况下才会启用
listen 部分
常常用于状态页面监控,以及后端 server 检查, 此部分是 frontend 部分和 backend 部分的结合体。
在 HAProxy1.3 版本之前,HAProxy 的所有配置选项都在这个部分中设置。为了保持兼容性,HAProxy 新的版本仍然保留了 listen 组件的配置方式。目前在 HAProxy 中,两种配置方式任选其一即可。
1 | listen admin_status # Frontend和Backend的组合体,监控组的名称,按需自定义名称 |
这个部分通过 listen 关键字定义了一个名为 “admin_stats” 的实例,其实就是定义了一个 HAProxy 的监控页面,每个选项的含义如下:
- stats refresh: 设置 HAProxy 监控统计页面自动刷新的时间。
- stats uri: 设置 HAProxy 监控统计页面的URL 路径,可随意指定。
例如、指定“stats uri /haproxy-status”,就可以过
http://IP:8888/haproxy-status
查看。 - stats realm: 设置登录 HAProxy 统计页面时密码框上的文本提示信息。
- stats auth: 设置登录 HAProxy 统计页面的用户名和密码。用户名和密码通过冒号分割。可为监控页面设置多个用户名和密码,每行一个。
- stats hide-version: 用来隐藏统计页面上 HAProxy 的版本信息。
- stats admin if TRUE: 通过设置此选项,可以在监控页面上手工启用或禁用后端真实服务器,仅在 haproxy1.4.9 以后版本有效。
1 | # 本例配置是某个后端服务,相当于 fronted 与 backend 的结合体 |
负载均衡策略
- roundrobin, rr: 简单轮询,基于权重进行轮询,在服务器的处理时间保持均匀分布时,这是最平衡,最公平的算法.此算法是动态的,这表示其权重可以在运行时进行调整.
- static-rr: 权重轮询,基于权重进行轮询,与roundrobin类似,但是为静态方法,在运行时调整其服务器权重不会生效.不过,其在后端服务器连接数上没有限制
- leastconnections: 最少连接数优先,新的连接请求被派发至具有最少连接数目的后端服务器. 此算法会将新的连接请求转发到具有最少连接数目的后端服务器。在会话时间较长的场景中推荐使用此算法 ,例如数据库负载均衡
- source: 请求源主机 IP 地址,基于请求源IP的算法。此算法先对请求的源IP进行HASH运算,然后将结果与后端服务器的权重总数相除后转发至某台匹配的后端服务器。
- uri: 请求 URI,此算法会对部分或整个URI进行HASH运算,再经过与服务器的总权重相除,最后转发到某台匹配的后端服务器上
- uri_param: 请求 URl 的参数,此算法会根据URL路径中的参数进行转发,这样可保证在后端真实服务器数据不变时,同一个用户的请求始终分发到同一台机器上
- hdr(name): 根据 HTTP Request Hander 锁定每一次 HTTP 请求,此算法根据HTTP头进行转发,如果指定的HTTP头名称不存在,则使用 roundrobin 算法进行策略转发
- rdp-cookie(name): 根据据 Cookie 锁定并哈希每一次 TCP 请求
ACL 规则
HAProxy 支持基于 ACL 规则的分发策略:
- 通过 ACL 规则检查客户端请求是否合法
- 符合 ACL 规则的客户端请求被提交到指定 backend
ACL 规则经常被用到 frontend section,使用方式:
1 | acl <acl_name> <acl_method> -i [匹配的路径或文件] |
示例
1 | acl www_policy hdr_reg(host) -i ^(www.z.cn|z.cn) |
常与 ACL 规则一起使用配置参数有 use_backend 和 default_backend,两者均用于指定 backend。
- use_backend:满足 ACL 规则的客户端请求就转发至该 backend
- default_backend:没有满足 ACL 规则的客户端请求转发至该 backend
HAProxy 实验示例
示例(一): HAProxy + Keepalived
HAProxy & Keepalived 组合成为高可用负载均衡解决方案。由 HAProxy 提供 backend 划分和负载均衡;由 Keepalived 提供负载均衡服务器的高可用以及 Real Server 集群的健康检查。
本次实验环境配置如下
服务器 | IP 地址 | 软件部署 |
---|---|---|
haproxy-master | 192.168.200.13 | haproxy + keepalived |
haproxy-backup | 192.168.200.14 | haproxy + keepalived |
web-1 | 192.168.200.15 | nginx |
web-2 | 192.168.200.16 | nginx |
本次实验使用的 VIP 为 192.168.200.100 以及 192.168.200.101
安装配置 HAProxy(主备都要安装配置)
使用 yum 安装 haproxy,需要先安装 epel 源,主备都要安装 haproxy 软件
1
2
3
4
5# 安装 epel 源
yum install -y epel-release
# 安装 haproxy
yum install -y haproxy配置 haproxy,修改
/etc/haproxy/haproxy.cfg
文件,修改后内容如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88global
log 127.0.0.1 local1 notice # 定义haproxy日志输出设置
ulimit-n 65535 # 设置每个进程的可用的最大文件描述符
maxconn 20480 # 默认最大连接数
chroot /var/lib/haproxy # chroot运行路径
user haproxy # 运行haproxy 用户
group haproxy # 运行haproxy 用户组
daemon # 以后台形式运行harpoxy
nbproc 1 # 设置进程数量
pidfile /var/run/haproxy.pid # haproxy 进程PID文件
defaults
mode http # 所处理的类别(7层代理http,4层代理tcp)
log global # 引入global定义的日志格式
maxconn 10140 # 最大连接数
option httplog # 日志类别为http日志格式
option http-server-close # 每次请求完毕后主动关闭http通道
option dontlognull # 不记录健康检查日志信息
option forwardfor # 如果后端服务器需要获得客户端的真实ip,需要配置的参数,
# 可以从http header 中获取客户端的IP
retries 3 # 3次连接失败就认为服务器不可用,也可以通过后面设置
option redispatch #《---该选项意思是指serverID对应的服务器挂掉后,强制定向到其他健康的服务器, 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常---》
stats refresh 30 # 设置统计页面刷新时间间隔
option abortonclose # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的连接
balance roundrobin # 设置默认负载均衡方式,轮询方式
#balance source # 设置默认负载均衡方式,类似于nginx的ip_hash
#contimeout 5000 # 设置连接超时时间,老版本设置方式,同 timeout connect 设置
#clitimeout 50000 # 设置客户端超时时间,老版本设置方式,同 timeout client 设置
#srvtimeout 50000 # 设置服务器超时时间,老版本设置方式,同 timeout server 设置
timeout http-request 10s # 默认http请求超时时间
timeout queue 1m # 默认队列超时时间
timeout connect 10s # 默认连接超时时间
timeout client 1m # 默认客户端超时时间
timeout server 1m # 默认服务器超时时间
timeout http-keep-alive 10s # 默认持久连接超时时间
timeout check 10s # 设置心跳检查超时时间
frontend http_80_in
bind 0.0.0.0:80 # 设置监听端口,即haproxy提供的web服务端口,和lvs的vip 类似
mode http # http 的7层模式
log global # 应用全局的日志设置
option httplog # 启用http的log
option httpclose # 每次请求完毕后主动关闭http通道,HAproxy不支持keep-alive模式
# 在 HTTP 头部添加 X-Forwarded-For,使得后端服务器可以获取原始请求的 Source IP
option forwardfor #如果后端服务器需要获得客户端的真实IP需要配置此参数,将可以从HttpHeader中获得客户端IP
# 在 HTTP 头部添加 X-Forwarded-Port,使得后端服务器可以知道原始请求的 Source Port
http-request set-header X-Forwarded-Port %[dst_port]
# 在使用 SSL 时添加 X-Forwarded-Proto
http-request add-header X-Forwarded-Proto https if { ssl_fc }
# ACL 匹配域,结果为 True or False
# acl url_static path_end -i .html .jpg .gif
# acl url_dynamic path_end -i .php
acl html url_reg -i \.html$
# 根据 acls 规则得到的布尔值来决定分发的 backend
use_backend httpservers if html
default_backend httpservers # 设置请求默认转发的后端服务池
backend httpservers # 定义 httpservers 服务器组。
mode http # http的7层模式
option redispatch
option abortonclose
balance roundrobin # 负载均衡的方式,轮询算法,为了看效果实验用轮询算法
# balance source # 负载均衡的方式,源哈希算法
cookie SERVERID # 允许插入serverid到cookie中,serverid后面可以定义
option httpchk GET /index.html # 心跳检测
# 后端业务服务器清单
server http1 192.168.200.15:80 maxconn 2000 cookie server1 weight 1 check inter 1s rise 2 fall 2
server http2 192.168.200.16:80 maxconn 2000 cookie server2 weight 1 check inter 1s rise 2 fall 2
listen admin_status # Frontend和Backend的组合体,监控组的名称,按需自定义名称
bind 0.0.0.0:8888 # 监听服务端口-HAproxy后台管理页面,这个端口可自定义设置,不可用已占用端口
# option httpchk GET /index.html # 后端真实主机监控检查方式
mode http # http的7层模式
log 127.0.0.1 local3 err # 错误日志记录
stats refresh 5s # 每隔5秒自动刷新监控页面
stats uri /proxy # 监控页面的url访问路径,自定义访问路径
stats realm Haproxy\ welcome # 监控页面的提示信息
stats auth admin:admin # 监控页面的用户和密码admin,可以设置多个用户名
stats auth admin1:admin1 # 监控页面的用户和密码admin1
stats hide-version # 隐藏统计页面上的HAproxy版本信息
stats admin if TRUE # 手工启用/禁用,后端服务器(haproxy-1.4.9以后版本)检查配置文件是否正确
1
2# haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid启动 haproxy 并配置开机启动
1
systemctl enable --now haproxy.service
致此,HAProxy 服务搭建完毕,只有上面的搭建成功后,才能继续下面的keepalived+HAproxy搭建双主热备高可用集群
haproxy 日志的配置
两台机器都配置 haproxy 的日志: 需要打开注释并添加 (如果有backup,backup上面也需要配置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 如果系统没有安装 rsyslog,使用以下命令安装
yum install -y rsyslog
# 配置 haproxy 日志输出
cat > /etc/rsyslog.d/haproxy.conf<<EOF
\$ModLoad imudp
\$UDPServerRun 514
\$FileCreateMode 0644
\$FileOwner haproxy
local1.* /var/log/haproxy.log
local1.error /var/log/haproxy_error.log
EOF
# 修改 rsyslog 的启动参数
sed -i 's/SYSLOGD_OPTIONS=""/SYSLOGD_OPTIONS="-c 2 -r -m 0"/' /etc/sysconfig/rsyslog重启 rsyslog 以及 haproxy
1
2systemctl restart rsyslog
systemctl restart haproxy查看日志
1
2
3
4
5
6
7
8
9
10
11# tailf /var/log/haproxy.log
Feb 28 17:37:34 localhost haproxy[3718]: Server httpservers/http1 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Feb 28 17:37:35 localhost haproxy[3721]: Server httpservers/http2 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Feb 28 17:37:35 localhost haproxy[3721]: backend httpservers has no server available!
Feb 28 17:40:32 localhost haproxy[3907]: Proxy http_80_in started.
Feb 28 17:40:32 localhost haproxy[3907]: Proxy http_80_in started.
Feb 28 17:40:32 localhost haproxy[3907]: Proxy httpservers started.
Feb 28 17:40:32 localhost haproxy[3907]: Proxy admin_status started.
Feb 28 17:40:32 localhost haproxy[3907]: Server httpservers/http1 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Feb 28 17:40:33 localhost haproxy[3910]: Server httpservers/http2 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Feb 28 17:40:33 localhost haproxy[3910]: backend httpservers has no server available!
Haproxy参数优化
随着企业网站负载增加,haproxy 参数优化相当重要,以下是重要参数的说明一下优化建议
优化参数 | 含义 |
---|---|
maxconn | 最大连接数,根据应用实际情况进行调整,推荐使用 10240 |
daemon | 守护进程模式,Haproxy可以使用非守护进程模式启动,建议使用守护进程模式启动 |
nbproc | 负载均衡的并发进程数,建议与当前服务器CPU核数相等或为其2倍 |
retries | 重试次数,主要用于对集群节点的检查,如果节点多,且并发量大,设置为2次或3次 |
option http-server-close | 主动关闭http请求选项,建议在生产环境中使用此选项 |
timeout http-keep-alive | 长连接超时时间,设置长连接超时时间,可以设置为10s |
timeout http-request | http请求超时时间,建议将此时间设置为5~10s,增加http连接释放速度 |
timeout client | 客户端超时时间,如果访问量过大,节点响应慢,可以将此时间设置短一些,建议设置为1min左右就可以了 |
部署 keepalived
安装配置 Keepalived,master 和 backup 都要部署
1
yum install -y keepalived
配置 haproxy-master 上的 Keepalived 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48! Configuration File for keepalived
global_defs {
router_id proxy-master # 自定义id不能重复
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 10 # 每10秒执行一次检查脚本
# weight 2
}
# 实例1 是MASTER服务
vrrp_instance VI_1 { # 实例名称也可以自定义,主从必须一致
state MASTER # 配置 HA1 为 Master
interface ens33 # 网卡名称根据自己的改
virtual_router_id 51 # 虚拟路由id,主从必须一致 配置同一个 VRID,范围在 [0-255] 之间
priority 100 # 优先级,MASTER比BACKUP高即可,数字差距尽量大一些
advert_int 1
authentication {
auth_type PASS # 主从保持一致
auth_pass 1111 # 主从保持一致
}
track_script { # 引用脚本
chk_haproxy # 脚本名称与上面定义的名称必须一致
}
virtual_ipaddress { # 虚拟ip地址
192.168.200.100/24 # 根据自己的修改
}
}
# 实例2 是BACKUP服务器
vrrp_instance VI_2 { # 实例名称也可以自定义,主从必须一致
state BACKUP # 置 HA1 为BACKUP
interface ens33 # 网卡名称根据自己的改
virtual_router_id 61 # 虚拟路由id,主从必须一致
priority 50 # 优先级,MASTER比BACKUP高即可,数字差距尽量大一些
advert_int 1
authentication {
auth_type PASS # 主从保持一致
auth_pass 1112 # 主从保持一致
}
virtual_ipaddress { # 虚拟ip地址
192.168.200.101/8 # 根据自己的修改
}
}配置 haproxy-backup 上的 Keepalived 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48! Configuration File for keepalived
global_defs {
router_id proxy-backup # 自定义id不能重复
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 10 # 每10秒执行一次检查脚本
# weight 2
}
# 实例1 是BACUP服务
vrrp_instance VI_1 { # 实例名称也可以自定义,主从必须一致
state BACKUP # 设置 HA2 为 Backup
interface ens33 # 网卡名称根据自己的改
virtual_router_id 51 # 虚拟路由id,主从必须一致
priority 50 # 优先级地于master
advert_int 1
authentication {
auth_type PASS # 主从保持一致
auth_pass 1111 # 主从保持一致
}
virtual_ipaddress { # 虚拟ip地址
192.168.200.100/24 # 根据自己的修改
}
}
# 实例2 是 MASTER 服务器
vrrp_instance VI_2 { # 实例名称也可以自定义,主从必须一致
state MASTER # 设置 HA2 为 MASTER
interface ens33 # 网卡名称根据自己的改
virtual_router_id 61 # 虚拟路由id,主从必须一致
priority 100 # 优先级,MASTER比BACKUP高即可,数字差距尽量大一些
advert_int 1
authentication {
auth_type PASS # 主从保持一致
auth_pass 1112 # 主从保持一致
}
track_script { # 引用脚本
chk_haproxy # 脚本名称与上面定义的名称必须一致
}
virtual_ipaddress { # 虚拟ip地址
192.168.200.101/24 # 根据自己的修改
}
}编写 chk_haproxy 脚本
以上我们只是实现了高可用,基于 Haproxy 的前提是 Haproxy 服务正常。如果有突发情况使得 HAproxy 服务不能启动,但是我们的 keepalived 服务是正常,这个时候用户是访问不到的,VIP也不会自动漂移到备用的节点服务器上。所以我们需要写一些代码来判断一下 Haproxy 服务是不是正常,如果不正常的话我们就将 keepalived 服务关掉,然后实现VIP的漂移,这个时候用户就不会出现无法访问的情况了。
- Keepalived 检测 haproxy 的脚本
/etc/keepalived/chk_haproxy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 让 Keepalived 以一定时间间隔执行一个外部脚本,脚本的功能是当 Haproxy 失败,则关闭本机的 Keepalived
# 具体端口和路径根据 HAproxy 提供的 web 服务设置来定
# 举例:如果是 8080 端口提供的 admin 页面,则应该为 curl -I http://localhost:8080/admin
# 或者 curl -I http://127.0.0.1/admin
# /usr/bin/curl -I http://localhost[:PORT][PATH] &>/dev/null # 具体端口根据 HAproxy提供的 web 服务设置
for i in `seq 1 5`
do
curl -I http://localhost:8888 &> /dev/null
# 如果访问测试不通过
if [ $? -ne 0 ];then
let m+=1
sleep 1 # 睡1秒
# 测试两次失败则重启 HAproxy 服务
if [ ${m} -eq 2 ];then
# 重启HAproxy服务
systemctl restart haproxy
# 重启成功则继续进行下一次检查
if [ $? -eq 0 ];then
echo "`date` haproxy restart successfully" >> /opt/m.txt
else
# 重启失败则,停止keepalived服务
systemctl stop keepalived
exit
fi
fi
# 测试失败3次则停止keepalived服务
if [ ${m} -ge 3 ];then
# 停止keepalived服务
# /etc/init.d/keepalived stop
systemctl stop keepalived
exit
fi
else
# 检测通过则跳出循环
break
fi
done- 给脚本添加执行权限
1
chmod a+x /etc/keepalived/chk_haproxy.sh # 一定要添加执行权限
- Keepalived 检测 haproxy 的脚本
启动 keepalived 服务,并配置开机启动。主从都要启动
注意:必须先启动 Haproxy,再启动keepalived,建议备用节点也添加上.
1
systemctl enable --now keepalived.service
查看主从的 IP信息,检查 VIP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41###### haproxy-master 主机的IP信息 ######
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:3e:c1:5e brd ff:ff:ff:ff:ff:ff
inet 192.168.200.13/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.200.100/24 scope global secondary ens33
valid_lft forever preferred_lft forever
inet6 fe80::c1a8:7f5b:bbda:8d15/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::fe7:5bc2:6628:7a1a/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::3c00:74cc:ac1b:c628/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
###### haproxy-backup 主机的 IP 信息 ######
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:35:4c:8e brd ff:ff:ff:ff:ff:ff
inet 192.168.200.14/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.200.101/24 scope global secondary ens33
valid_lft forever preferred_lft forever
inet6 fe80::c1a8:7f5b:bbda:8d15/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::fe7:5bc2:6628:7a1a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::3c00:74cc:ac1b:c628/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
安装配置后端 web 服务
后端两台真实 web 服务器都安装 nginx,然后配置主页显示,如下
1
2
3
4
5
6
7
8# 安装 nginx
yum install -y nginx
# 配置主页显示
echo "$HOSTNAME Server" > /usr/share/nginx/html/index.html
# 启动并配置nginx开机启动
systemctl enable --now nginx使用客户端测试访问
http://192.168.200.100
和http://192.168.200.101
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.100
centos7-04 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.100
centos7-03 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.100
centos7-04 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.100
centos7-03 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.101
centos7-04 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.101
centos7-03 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.101
centos7-04 Server
wanwu@wanwudeMac-mini ~ % elinks --dump http://192.168.200.101
centos7-03 Server-
可以看到,两台 Haproxy 各收到了 4 条请求记录