文章目录
HAProxy
HAProxy概述
定义:
HAProxy是一种提供高可用性、负载均衡以及基于TCP和HTTP应用的代理解决方案。它是免费、快速且可靠的,尤其适用于并发量大的web站点,这些站点通常还需要会话保持或七层处理。
运行模式:
HAProxy的运行模式使其能够简单且安全地整合到当前的架构中,同时保护web服务器不被直接暴露在网络上。
HAProxy的主要特性
- 可靠性和稳定性:与硬件级的F5负载均衡设备相媲美。
- 并发处理能力:最高可同时维护40000-50000个并发连接,单位时间内处理的最大请求数为20000个,最大处理能力可达10Git/s。
- 负载均衡算法:支持多达8种负载均衡算法。
- 会话保持:支持Session会话保持和Cookie的引导。
- 健康检查:支持通过获取指定的URL来检测后端服务器的状态。
- 虚机主机功能:实现web负载均衡更加灵活。
- 独特功能:支持连接拒绝、全透明代理等。
- ACL支持:用于访问控制,功能强大。
- 协议支持:支持TCP和HTTP协议的负载均衡转发。
- 客户端keepalive功能:减少客户端与HAProxy的多次三次握手,让多个请求在一个TCP连接中完成。
HAProxy负载均衡策略
- roundrobin:简单的轮询。
- static-rr:根据权重进行分配。
- leastconn:最少连接者先处理。
- source:根据请求源IP进行分配。
- uri:根据请求的URI进行分配,常用于CDN。
- url_param:根据请求的URL参数进行分配。
- hdr(name):根据HTTP请求头来锁定每一次HTTP请求。
- rdp-cookie(name):根据cookie(name)来锁定并哈希每一次TCP请求。
LVS、Nginx、Haproxy的区别
负载均衡转发性能
- 硬件负载均衡 F5 > LVS > Haproxy > Nginx
支持的代理类型
- LVS
- 基于Linux内核实现的软负载均衡。
- 只支持四层代理转发。
- 不支持正则表达式处理。
- 不能做动静分离。
- Nginx & Haproxy
- 基于应用层实现的软负载均衡。
- 支持四层和七层代理转发。
- 支持正则表达式处理。
- 能做动静分离。
配置维护
-
LVS
- 实施配置复杂。
- 维护成本相对较高。
-
Nginx & Haproxy
- 配置简单。
- 维护成本较低。
健康检查
- LVS
- 可以配合Keepalived实现高可用。
- 支持TCP端口或HTTP URL方式的健康检查。
- Nginx
- 默认只支持被动方式的健康检查。
- 主动健康检查需要安装第三方模块(nginx_upstream_check_module)。
- Haproxy
- 默认支持主动的TCP端口、HTTP URL等方式的健康检查。
Haproxy的8种调度算法
- roundrobin:轮询
- static-rr:加权轮询
- leastconn:最少连接
- source:根据源地址做哈希
- uri:根据请求的URI地址做哈希
- url_param:根据请求的URL路径里传递的参数做哈希
- hdr(NAME):根据请求头的字段做哈希
- rdp-cookie(NAME):根据cookie里的字段做哈希
Haproxy的3种会话保持方式
- 源地址hash
balance source
- 设置cookie
cookie HA_STICKY_dy insert indirect nocache server tomcatsrv1 192.168.80.11:8080 cookie tomcatsrv1
- 会话粘性表stick-table
stick-table type ip size 5k expire 1m stick on src
Haproxy搭建Web群集
环境配置
- Haproxy服务器:192.168.80.10
- Nginx服务器1:192.168.80.100
- Nginx服务器2:192.168.80.101
- 客户端:192.168.80.200
Haproxy服务器部署
-
关闭防火墙并传输软件包
systemctl stop firewalld setenforce 0 wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.2.tar.gz
-
安装Haproxy
yum install -y pcre-devel bzip2-devel gcc gcc-c++ make tar zxvf haproxy-1.7.2.tar.gz cd haproxy-1.7.2/ make TARGET=linux2628 ARCH=x86_64 make install PREFIX=/usr/local/haproxy
-
Haproxy服务器配置
- 创建用户和目录
useradd -M -s /sbin/nologin haproxy mkdir -p /etc/haproxy
- 安装Haproxy
yum install -y haproxy
- 配置文件
haproxy.cfg
# 全局配置 global # 将info级别的日志发送到127.0.0.1的local0接口 log 127.0.0.1 local0 info # 将warning级别的日志发送到127.0.0.1的local1接口 log 127.0.0.1 local1 warning # 设置最大连接数为30000 maxconn 30000 # 指定haproxy进程号的文件路径 pidfile /var/run/haproxy.pid # 以haproxy用户身份运行haproxy进程 user haproxy # 以haproxy组身份运行haproxy进程 group haproxy # 以守护进程方式运行haproxy daemon # 在后端服务器数量较多的场景中,增加健康检查的时间间隔随机性,避免所有服务器同时进行健康检查带来的意外问题 spread-checks 2 # 默认配置 defaults # 使用全局的日志配置 log global # 设置工作模式为http mode http # 使用keepAlive连接,后端为静态建议使用http-keep-alive,后端为动态应用程序建议使用http-server-close option http-keep-alive # 记录客户端IP在X-Forwarded-For头域中,haproxy将在发往后端的请求中加上"X-Forwarded-For"首部字段 option forwardfor # 开启httplog,在日志中记录http请求、session信息等 option httplog # 不在日志中记录空连接 option dontlognull # 当某后端down掉使得haproxy无法转发携带cookie的请求到该后端时,将其转发到别的后端上 option redispatch # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 option abortonclose # 设置最大连接数为20000 maxconn 20000 # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后会将对应后端服务器标记为不可用 retries 3 # 设置http请求超时时间,此为等待客户端发送完整请求的最大时长,用于避免类DoS攻击 timeout http-request 2s # 设置客户端请求在队列中的最大时长 timeout queue 3s # 设置haproxy和服务端建立连接的最大时长,新版本中替代contimeout,该参数向后兼容 timeout connect 1s # 设置和客户端保持空闲连接的超时时长,在高并发下可稍微短一点,可设置为10秒以尽快释放连接,新版本中替代clitimeout timeout client 10s # 设置和服务端保持空闲连接的超时时长,局域网内建立连接很快,所以尽量设置短一些,特别是高并发时,新版本中替代srvtimeout timeout server 2s # 设置和客户端保持长连接的最大时长。优先级高于timeout http-request 也高于timeout client timeout http-keep-alive 10s # 和后端服务器成功建立连接后到最终完成检查的最大时长(不包括建立连接的时间,只是读取到检查结果的时长) timeout check 2s # 定义前端服务实例 frontend http-in # 绑定监听地址和端口,指定为*或0.0.0.0时,将监听当前系统的所有IPv4地址 bind *:80 # 定义此端口上的maxconn maxconn 18000 # 定义ACL,当uri以/static /images开头时,ACL[url_static1]为true acl url_static1 path_beg -i /static /images # 定义ACL,当uri以.jpg .jpeg .gif .png .html .htm .txt结尾时,ACL[url_static2]为true acl url_static2 path_end -i .jpg .jpeg .gif .png .html .htm .txt # 当ACL[url_static1]为true时,定向到后端域ms1中 use_backend ms1 if url_static1 # 当ACL[url_static2]为true时,定向到后端域ms2中 use_backend ms2 if url_static2 # 其他情况时,定向到后端域dynamic_group中 default_backend dynamic_group # 定义后端服务实例组ms1 backend ms1 # 使用轮询算法 balance roundrobin # 基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康 option httpchk GET /test.html # 定义后端服务器ms1.inst1,IP为192.168.80.100,端口为80,最大连接数为5000,启用健康检查 server ms1.inst1 192.168.80.100:80 maxconn 5000 check inter 2000 rise 2 fall 3 # 定义后端服务器ms1.inst2,IP为192.168.80.100,端口为81,最大连接数为5000,启用健康检查 server ms1.inst2 192.168.80.100:81 maxconn 5000 check # 定义后端服务实例组ms2 backend ms2 # 使用轮询算法 balance roundrobin # 基于http协议来做健康状况检查,只有返回状态码为2xx或3xx的才认为是健康的,其余所有状态码都认为不健康 option httpchk GET /test.html # 定义后端服务器ms2.inst1,IP为192.168.80.101,端口为80,最大连接数为5000,启用健康检查 server ms2.inst1 192.168.80.101:80 maxconn 5000 check # 定义后端服务器ms2.inst2,IP为192.168.80.101,端口为81,最大连接数为5000,启用健康检查 server ms2.inst2 192.168.80.101:81 maxconn 5000 check # 定义后端服务实例组dynamic_group backend dynamic_group # 使用轮询算法 balance roundrobin # 使用http-server-close选项,表示连接建立后,服务器端主动关闭连接 option http-server-close # 在响应中插入名为HA_STICKY_dy的cookie,其值为对应的server定义中指定的值,并根据请求中此cookie的值决定转发至哪个server cookie HA_STICKY_dy insert indirect nocache # 定义后端服务器appsrv1,IP为192.168.80.100,端口为8080,最大连接数为5000,启用健康检查 server appsrv1 192.168.80.100:8080 cookie appsrv1 maxconn 5000 check # 定义后端服务器appsrv2,IP为192.168.80.101,端口为8080,最大连接数为5000,启用健康检查 server appsrv2 192.168.80.101:8080 cookie appsrv2 maxconn 5000 check # 定义监控页面 listen stats # 绑定监听地址和端口 bind *:1080 # 启用统计报告监控 stats enable # 设置每30秒更新监控数据 stats refresh 30s # 设置访问监控页面的uri stats uri /stats # 设置监控页面的认证提示 stats realm HAProxy\ Stats # 设置监控页面的用户名和密码 stats auth admin:admin
- 创建用户和目录
-
添加Haproxy系统服务
vim /etc/init.d/haproxy #!/bin/bash #chkconfig: 2345 90 30 #description: Haproxy Service Control Script # 设置相关变量 PROGDIR=/usr/local/haproxy PROGNAME=haproxy DAEMON=$PROGDIR/sbin/$PROGNAME CONFIG=/etc/haproxy/$PROGNAME.cfg PIDFILE=/var/run/$PROGNAME.pid DESC="HAProxy daemon" SCRIPTNAME=/etc/init.d/$PROGNAME # 如果haproxy二进制文件不存在,则优雅退出 # Gracefully exit if the package has been removed. test -x $DAEMON || exit 0 # 启动函数 start() { echo -e "Starting $DESC: $PROGNAME\n" $DAEMON -f $CONFIG echo "......" } # 停止函数 stop() { echo -e "Stopping $DESC: $PROGNAME\n" haproxy_pid="$(cat $PIDFILE)" kill $haproxy_pid echo "......" } # 重启函数 restart() { echo -e "Restarting $DESC: $PROGNAME\n" $DAEMON -f $CONFIG -p $PIDFILE -sf $(cat $PIDFILE) echo "......" } # 根据传入的参数执行相应操作 case "$1" in start) start ;; stop) stop ;; restart) restart ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart}" exit 1 ;; esac exit 0
cd /etc/init.d/ chmod +x haproxy # 赋予脚本执行权限 chkconfig --add /etc/init.d/haproxy # 将脚本添加到系统服务 ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin/haproxy # 创建haproxy命令的软链接 haproxy -c -f haproxy.cfg # 检查haproxy配置文件的语法 service haproxy start # 启动haproxy服务 # 或者使用 /etc/init.d/haproxy start # 另一种启动haproxy服务的方式
节点服务器部署
- 安装Nginx
systemctl stop firewalld setenforce 0 yum install -y pcre-devel zlib-devel gcc gcc-c++ make useradd -M -s /sbin/nologin nginx cd /opt tar zxvf nginx-1.12.0.tar.gz -C /opt/ cd nginx-1.12.0/ ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx && make && make install
- 配置Nginx
- 服务器1
echo "this is kgc web" > /usr/local/nginx/html/test.html
- 服务器2
echo "this is benet web" > /usr/local/nginx/html/test.html
- 服务器1
- 启动Nginx
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ nginx
测试Web群集
- 在客户端浏览器打开
http://192.168.80.10/test.html
,不断刷新测试负载均衡效果。 - 访问监控页面
http://192.168.80.10:1080/stats
,输入用户名密码admin/admin
进行验证。
HAProxy日志管理
在生产环境中,为了更好地管理HAProxy的日志,通常会单独定义日志输出,并将不同级别的日志记录到不同的文件中。
方法一
- 修改HAProxy配置文件
编辑/etc/haproxy/haproxy.cfg
文件,将info和notice级别的日志分别输出到不同的设备文件中。global log /dev/log local0 info log /dev/log local0 notice ......
- 修改rsyslog配置
为了便于管理,将HAProxy相关的配置独立定义到/etc/rsyslog.d/haproxy.conf
文件中。
这段配置将HAProxy的info日志记录到if ($programname == 'haproxy' and $syslogseverity-text == 'info') then -/var/log/haproxy/haproxy-info.log &~ if ($programname == 'haproxy' and $syslogseverity-text == 'notice') then -/var/log/haproxy/haproxy-notice.log &~
/var/log/haproxy/haproxy-info.log
,将notice日志记录到/var/log/haproxy/haproxy-notice.log
。&~
表示当日志写入到日志文件后,rsyslog停止处理这个信息。 - 重启服务
service rsyslog restart service haproxy restart
- 查看日志
tail -f /var/log/haproxy/haproxy-info.log
方法二
- 修改HAProxy配置文件
编辑/etc/haproxy/haproxy.cfg
文件,将info及以上级别的日志发送到rsyslog的local0接口,将warning及以上级别的日志发送到rsyslog的local1接口。
注:在生产环境中,建议将日志级别调整为notice,以减少磁盘空间的占用。global ...... log 127.0.0.1 local0 info log 127.0.0.1 local1 warning ......
- 为rsyslog添加HAProxy日志的配置
创建/var/log/haproxy
目录,并编辑/etc/rsyslog.d/haproxy.conf
文件。$ModLoad imudp $UDPServerRun 514 $FileCreateMode 0644 $FileOwner haproxy local0.* /var/log/haproxy/haproxy.log local1.* /var/log/haproxy/haproxy_warn.log
- 修改rsyslog的启动参数
编辑/etc/sysconfig/rsyslog
文件,添加以下选项。SYSLOGD_OPTIONS="-c 2 -r -m 0"
- 重启服务
service rsyslog restart service haproxy restart
- 查看日志
tail -f /var/log/haproxy/haproxy.log
使用 Keepalived 实现 HAProxy 高可用
安装 Keepalived
首先,确保在所有需要实现高可用的服务器上安装 Keepalived。
yum install -y keepalived
配置健康检查脚本
创建一个脚本来检查 HAProxy 实例是否正在运行。这个脚本将用于 Keepalived 的健康检查机制。
vim /etc/keepalived/check_haproxy.sh
脚本内容如下:
#!/bin/bash
# 使用 killall -0 检查 haproxy 实例是否存在,性能高于 ps 命令
if ! killall -0 haproxy; then
systemctl stop keepalived
fi
赋予脚本执行权限:
chmod +x /etc/keepalived/check_haproxy.sh
配置 Keepalived
编辑 Keepalived 的主配置文件 /etc/keepalived/keepalived.conf
。
vim /etc/keepalived/keepalived.conf
配置文件内容如下:
! Configuration File for keepalived
global_defs {
router_id LVS_HA1 # 虚拟路由名称
}
# HAProxy 健康检查配置
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh" # 指定健康检查脚本
interval 2 # 脚本运行周期(秒)
weight 2 # 每次检查的加权权重值
}
# 虚拟路由配置
vrrp_instance VI_1 {
state MASTER # 本机实例状态,MASTER/BACKUP
interface ens33 # 本机网卡名称
virtual_router_id 51 # 虚拟路由编号,主备机保持一致
priority 100 # 本机初始权重,备机设置小于主机的值
advert_int 1 # 争抢虚地址的周期(秒)
virtual_ipaddress {
192.168.80.100 # 虚地址IP,主备机保持一致
}
track_script {
chk_haproxy # 对应的健康检查配置
}
}
启动 Keepalived
启动 Keepalived 服务以应用配置。
systemctl start keepalived
验证虚拟 IP 地址
使用 ip addr
命令查看虚拟 IP 地址是否已正确绑定到网络接口。
ip addr
故障切换测试
为了验证高可用性配置是否有效,可以停止当前 MASTER 主机的 HAProxy 实例,观察虚拟 IP 地址是否自动切换到备份节点。
service haproxy stop
此时当主节点出现问题时,Keepalived 将自动将虚拟 IP 地址切换到备份节点,确保服务的连续性。
内核优化
编辑 /etc/sysctl.conf
文件以进行内核参数优化,这些参数有助于提高系统的网络性能和稳定性。
# 开启重用。允许将TIME-WAIT sockets重用于新的TCP连接,默认0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
# 用于向外连接的端口范围。缺省情况下很小
net.ipv4.ip_local_port_range = 1024 65535
# SYN队列长度,记录尚未收到客户端确认信息的连接请求的最大值。默认为1024,加大队列长度可容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 10240
# 表示系统同时保持TIME_WAIT最大数量,如果超过,TIME_WAIT将立刻被清除并打印警告信息。默认180000,此项参数可控制TIME_WAIT 最大数量
net.ipv4.tcp_max_tw_buckets = 5000
# 系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上,如超过,连接将即刻被复位并打印警告信息,这个限制仅是为防止简单的DoS攻击,不能过分依靠它或人为减小这个值,更应该增加这个值(如果增加内存后)
net.ipv4.tcp_max_orphans = 3276800
# 为打开对端的连接,内核需发送个SYN并附带个回应前一个SYN的ACK。即三次握手中的第二次握手。该设置决定内核放弃连接前发SYN+ACK包的数量。
net.ipv4.tcp_synack_retries = 3
# 如web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而 nginx 定义的 NGX_LISTEN_BACKLOG 默认511,所以有必要调整这个值。
net.core.somaxconn = 32768
应用更改并重新加载内核参数:
sysctl -p