负载均衡(3)

文章目录

  • 一、HAProxy介绍
    • 企业版
    • 社区版
    • 版本对比
    • HAProxy功能
    • 支持功能
    • 不具备的功能
  • 二、编译安装HAProxy
    • 解决lua环境
      • Centos 基础环境
    • 编译安装HAProxy
    • 验证HAProxy版本
    • HAProxy启动脚本
    • 配置文件
    • 启动haproxy
    • 验证haproxy状态
    • 查看haproxy的状态页面
  • 三、HAProxy基础配置详解
    • global配置
      • global 配置参数说明
      • 多进程和线程
    • 日志配置
      • HAProxy配置
      • Rsyslog配置
      • 验证HAProxy日志
  • 四、Proxies配置
    • Proxies配置-defaults
    • Proxies配置-frontend
    • Proxies配置-backend
      • option 配置
    • frontend+backend配置实例
    • listen替代frontend+backend
    • 使用子配置文件保存配置
  • 五、HAProxy调度算法
    • 静态算法
      • static-rr
      • first
    • 动态算法
      • roundrobin
      • leastconn
      • random
    • 其他算法
      • source
      • map-base取模法
      • 一致性hash
      • uri
      • url_param
      • hdr
      • rdp-cookie
    • 算法总结
    • 各算法使用场景
  • 六、HAProxy状态页
    • backend server信息
  • 七、利用状态页实现haproxy服务器的健康性检查

一、HAProxy介绍

​ HAProxy是法国开发者威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件,是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计,目前最新TLS版本为2.0

历史版本:

  • 历史版本更新功能:1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2-dev
  • 1.8:多线程,HTTP/2缓存……
  • 1.7:服务器动态配置,多类型证书……
  • 1.6:DNS解析支持,HTTP连接多路复用……
  • 1.5:开始支持SSL,IPV6,会话保持……

从2013年HAProxy 分为社区版和企业版,企业版将提供更多的特性和功能以及全天24小时的技术支持等服务。

企业版

企业版网站:https://www.haproxy.com/
负载均衡(3)_第1张图片

社区版

社区版网站:http://www.haproxy.org/

github:https://github.com/haproxy
负载均衡(3)_第2张图片

版本对比

功能 社区版 企业版
高级HTTP / TCP负载平衡和持久性 支持 支持
高级健康检查 支持 支持
应用程序加速 支持 支持
高级安全特性 支持 支持
高级管理 支持 支持
HAProxy Dev Branch新功能 支持
24*7 支持服务 支持
实时仪表盘 支持
VRRP和Route Health Injection HA工具 支持
ACL,映射和TLS票证密钥同步 支持
基于应用程序的高级DDoS和Bot保护(自动保护) 支持
Bot(机器人)监测 支持
Web应用防火墙 支持
HTTP协议验证 支持
实时集群追踪 支持

HAProxy功能

负载均衡(3)_第3张图片
负载均衡(3)_第4张图片

支持功能

  • TCP 和 HTTP反向代理
  • SSL/TSL服务器
  • 可以针对HTTP请求添加cookie,进行路由后端服务器
  • 可平衡负载至后端服务器,并支持持久连接
  • 支持所有主服务器故障切换至备用服务器
  • 支持专用端口实现监控服务
  • 支持停止接受新连接请求,而不影响现有连接
  • 可以在双向添加,修改或删除HTTP报文首部
  • 响应报文压缩
  • 支持基于pattern实现连接请求的访问控制
  • 通过特定的URI为授权用户提供详细的状态信息
  • 支持动态程序的反向代理
  • 支持基于数据库的反向代理

不具备的功能

  • 正向代理–squid,nginx
  • 缓存代理–varnish
  • web服务–nginx、tengine、apache、php、tomcat
  • UDP–目前不支持UDP协议
  • 单机性能–相比LVS性能较差

二、编译安装HAProxy

编译安装HAProxy 2.0 LTS版本,更多源码包下载地址:http://www.haproxy.org/download/

  • centos7自带的源中yum安装的版本是较老的1.5的版本
    负载均衡(3)_第5张图片

解决lua环境

HAProxy 支持基于lua实现功能扩展,lua是一种小巧的脚本语言,于1993年由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组开发,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Lua 官网:www.lua.org

  • Lua 应用场景
    • 游戏开发
    • 独立应用脚本
    • Web 应用脚本
    • 扩展和数据库插件,如MySQL Proxy
    • 安全系统,如入侵检测系统

Centos 基础环境

参考链接:http://www.lua.org/start.html
负载均衡(3)_第6张图片
由于CentOS7 之前版本自带的lua版本比较低并不符合HAProxy要求的lua最低版本(5.3)的要求,因此需要编译安装较新版本的lua环境,然后才能编译安装HAProxy,过程如下

  • 当前系统版本
[root@localhost ~]# lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
  • 安装基础命令及编译依赖环境
[root@localhost ~]# yum -y install gcc readline-devel
[root@localhost ~]# wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
[root@localhost ~]# tar xvf lua-5.3.5.tar.gz -C /usr/local/src
[root@localhost ~]# cd /usr/local/src/lua-5.3.5
[root@localhost lua-5.3.5]# make linux test
  • 查看编译安装的版本
[root@localhost lua-5.3.5]# src/lua -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio

编译安装HAProxy

  • HAProxy 1.8及1.9版本编译参数
make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
  • HAProxy 2.0以上版本编译参数
[root@localhost ~]# yum -y install gcc openssl-devel pcre-devel systemd-devel
[root@localhost ~]# wget http://www.haproxy.org/download/2.1/src/haproxy-2.1.3.tar.gz
[root@localhost ~]# tar xvf haproxy-2.1.3.tar.gz -C /usr/local/src
[root@localhost ~]# cd /usr/local/src/haproxy-2.1.3/
[root@localhost haproxy-2.1.3]# cat README
  • 参考INSTALL文件进行编译安装
[root@localhost haproxy-2.1.3]# make ARCH=x86_64 TARGET=linux-glibc \
USE_PCRE=1 \
USE_OPENSSL=1 \
USE_ZLIB=1 \
USE_SYSTEMD=1 \
USE_LUA=1 \
LUA_INC=/usr/local/src/lua-5.3.5/src/ \
LUA_LIB=/usr/local/src/lua-5.3.5/src/
[root@localhost haproxy-2.1.3]# make install PREFIX=/apps/haproxy
[root@localhost haproxy-2.1.3]# ln -s /apps/haproxy/sbin/haproxy /usr/sbin/
  • 查看生成的文件
[root@localhost ~]# tree -C /apps/haproxy/
/apps/haproxy/
├── doc
│ 	└── haproxy
│ 	├── 51Degrees-device-detection.txt
│ 	├── architecture.txt
│ 	├── close-options.txt
│ 	├── configuration.txt
│ 	├── cookie-options.txt
│ 	├── DeviceAtlas-device-detection.txt
│ 	├── intro.txt
│ 	├── linux-syn-cookies.txt
│ 	├── lua.txt
│ 	├── management.txt
│ 	├── netscaler-client-ip-insertion-protocol.txt
│ 	├── network-namespaces.txt
│ 	├── peers.txt
│ 	├── peers-v2.0.txt
│ 	├── proxy-protocol.txt
│ 	├── regression-testing.txt
│ 	├── seamless_reload.txt
│ 	├── SOCKS4.protocol.txt
│ 	├── SPOE.txt
│ 	└── WURFL-device-detection.txt
├── sbin
│ 	└── haproxy
└── share
	└── man
		└── man1
			└── haproxy.1

6 directories, 22 files

验证HAProxy版本

[root@localhost ~]# which haproxy
/usr/sbin/haproxy
[root@localhost ~]# haproxy -v
HA-Proxy version 2.1.3 2020/02/12 - https://haproxy.org/
Status: stable branch - will stop receiving fixes around Q1 2021.
Known bugs: http://www.haproxy.org/bugs/bugs-2.1.3.html

[root@localhost ~]# haproxy -vv
HA-Proxy version 2.1.3 2020/02/12 - https://haproxy.org/
Status: stable branch - will stop receiving fixes around Q1 2021.
Known bugs: http://www.haproxy.org/bugs/bugs-2.1.3.html
Build options :
	TARGET = linux-glibc
	CPU = generic
	CC = gcc
	CFLAGS = -m64 -march=x86-64 -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-old-style-declaration -Wno-ignored-qualifiers -Wno-clobbered -Wno-missing-field-initializers -Wtype-limits
	OPTIONS = USE_PCRE=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1 USE_SYSTEMD=1
	
Feature list : +EPOLL -KQUEUE -MY_EPOLL -MY_SPLICE +NETFILTER +PCRE -PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED -REGPARM -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H -VSYSCALL +GETADDRINFO +OPENSSL +LUA +FUTEX +ACCEPT4 -MY_ACCEPT4 +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
	bufsize = 16384, maxrewrite = 1024, maxpollevents = 200
	
Built with multi-threading support (MAX_THREADS=64, default=4).
Built with OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
Running on OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : SSLv3 TLSv1.0 TLSv1.1 TLSv1.2
Built with Lua version : Lua 5.3.5
Built with network namespace support.
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE version : 8.32 2012-11-30
Running on PCRE version : 8.32 2012-11-30
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Encrypted password support via crypt(3): yes
Built with zlib version : 1.2.7
Running on zlib version : 1.2.7
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")

Available polling systems :
	epoll : pref=300, test result OK
	poll : pref=200, test result OK
	select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
	h2 : mode=HTTP side=FE|BE mux=H2
	fcgi : mode=HTTP side=BE mux=FCGI
	<default> : mode=HTTP side=FE|BE mux=H1
    <default> : mode=TCP side=FE|BE mux=PASS
    
Available services : none

Available filters :
	[SPOE] spoe
	[CACHE] cache
	[FCGI] fcgi-app
	[TRACE] trace
	[COMP] compression

HAProxy启动脚本

[root@localhost ~]# vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p
/var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
  • 默认缺少配置文件,无法启动
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start haproxy
Job for haproxy.service failed because the control process exited with error code. See "systemctl status haproxy.service" and "journalctl -xe" for details.


[root@localhost ~]# tail /var/log/messages
Jul 13 10:39:33 localhost systemd: Starting HAProxy Load Balancer...
Jul 13 10:39:33 localhost haproxy: [ALERT] 193/103933 (8156) : Cannot open configuration file/directory /etc/haproxy/haproxy.cfg : No such file or directory
Jul 13 10:39:33 localhost systemd: haproxy.service: control process exited, code=exited status=1
Jul 13 10:39:33 localhost systemd: Failed to start HAProxy Load Balancer.
Jul 13 10:39:33 localhost systemd: Unit haproxy.service entered failed state.
Jul 13 10:39:33 localhost systemd: haproxy.service failed.

配置文件

  • 创建自定义的配置文件
[root@localhost ~]# mkdir /etc/haproxy
[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
global
	maxconn 100000
	chroot /apps/haproxy
	stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
	#uid 99
	#gid 99
	user haproxy
	group haproxy
	daemon
	#nbproc 4
	#cpu-map 1 0
	#cpu-map 2 1
	#cpu-map 3 2
	#cpu-map 4 3
	pidfile /var/lib/haproxy/haproxy.pid
	log 127.0.0.1 local2 info
	
defaults
	option http-keep-alive
	option forwardfor
	maxconn 100000
	mode http
	timeout connect 300000ms
	timeout client 300000ms
	timeout server 300000ms

listen stats
	mode http
	bind 0.0.0.0:9999
	stats enable
	log global
	stats uri /haproxy-status
	stats auth admin:123456

listen web_port
	bind 192.168.175.10:80
	mode http
	log global
	server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

启动haproxy

[root@localhost ~]# mkdir /var/lib/haproxy
[root@localhost ~]# useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy
[root@localhost ~]# systemctl enable --now haproxy

验证haproxy状态

​ haproxy.cfg文件中定义了chroot、pidfile、user、group等参数,如果系统没有相应的资源会导致haproxy无法启动,具体参考日志文件 /var/log/messages

[root@localhost ~]# systemctl status haproxy
[root@localhost ~]# pstree -p |grep haproxy

查看haproxy的状态页面

  • 浏览器访问http://192.168.175.10:9999/haproxy-status
  • 用户名admin,密码123456,这个是在配置文件里定义好的
    负载均衡(3)_第7张图片
    负载均衡(3)_第8张图片

三、HAProxy基础配置详解

官方文档:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html

HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是global和proxies部分

  • global:全局配置段

    • 进程及安全配置相关的参数
    • 性能调整相关参数
    • Debug参数
  • proxies:代理配置段

    • defaults:为frontend, backend, listen提供默认配置
    • frontend:前端,相当于nginx中的server {}
    • backend:后端,相当于nginx中的upstream {}
    • listen:同时拥有前端和后端配置

global配置

global 配置参数说明

官方文档:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#3

chroot #锁定运行目录
deamon #以守护进程运行
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin process 1 #socket文件
user, group, uid, gid #运行haproxy的用户身份
nbproc n #开启的haproxy work 进程数,默认进程数是一个
#nbthread 1 #指定每个haproxy进程开启的线程数,默认为每个进程一个线程,和nbproc互斥(版本有关)
#如果同时启用nbproc和nbthread 会出现以下日志的错误,无法启动服务
Apr 7 14:46:23 haproxy haproxy: [ALERT] 097/144623 (1454) : config : cannot enable multiple processes if multiple threads are configured. Please use either nbproc or nbthread but not both.

cpu-map 1 0 #绑定haproxy 进程至指定CPU,将第一个work进程绑定至0号CPU
maxconn n #每个haproxy进程的最大并发连接数
maxsslconn n #每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下
maxconnrate n #每个进程每秒创建的最大连接数量
spread-checks n #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间,默认值0
pidfile #指定pid文件路径
log 127.0.0.1 local2 info #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个

多进程和线程

范例:多进程和socket文件

[root@localhost ~]# vim /etc/haproxy/haproxy.cfg
global
	maxconn 100000
	chroot /apps/haproxy
	stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
	stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
	user haproxy
	group haproxy
	daemon
	nbproc 2

[root@localhost ~]# systemctl restart haproxy
[root@localhost ~]# pstree -p |grep haproxy
	|-haproxy(8395)-+-haproxy(8399)
	| `-haproxy(8400)
[root@localhost ~]# ll /var/lib/haproxy/
总用量 4
-rw-r--r--. 1 root root 5 713 10:56 haproxy.pid
srw-------. 1 root root 0 713 10:56 haproxy.sock1
srw-------. 1 root root 0 713 10:56 haproxy.sock2

日志配置

HAProxy配置

# 在global配置项定义
log 127.0.0.1 local{1-7} #基于syslog记录日志到指定设备,级别有(err、warning、info、debug),在1-7中选择一个等级
#emerg 0 系统不可用 alert 1 必须马上采取行动的事件 crit 2 关键的事件 err 3 错误事件warning 4 警告事件 notice 5 普通但重要的事件 info 6 有用的信息 debug 7 调试信息
listen web_port
	bind 127.0.0.1:80
	mode http
	log global #开启当前web_port的日志功能,默认不记录日志
	server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

# systemctl restart haproxy

Rsyslog配置

[root@localhost ~]# vim /etc/rsyslog.conf

$ModLoad imudp
$UDPServerRun 514
......
#local3.* /var/log/boot.log
local7.* /var/log/haroxy.log

......

# systemctl restart rsyslog

验证HAProxy日志

  • 重启syslog服务并访问app页面,然后验证是否生成日志
[root@localhost ~]# tail -f /var/log/haproxy.log
Aug 14 20:21:06 localhost haproxy[18253]: Connect from 192.168.0.1:3050 to 10.0.0.7:80 (web_host/HTTP)
Aug 14 20:21:06 localhost haproxy[18253]: Connect from 192.168.0.1:3051 to 10.0.0.7:80 (web_host/HTTP)
Aug 14 20:21:06 localhost haproxy[18253]: Connect from 192.168.0.1:3050 to 10.0.0.7:80 (web_host/HTTP)

四、Proxies配置

官方文档:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4

  • defaults []
    • 默认配置项,针对以下的frontend、backend和listen生效,可以多个name也可以没有name
  • frontend
    • 前端servername,类似于Nginx的一个虚拟主机 server和LVS服务集群。
  • backend
    • 后端服务器组,等于nginx的upstream和LVS中的RS服务器
  • listen
    • 将frontend和backend合并在一起配置,相对于frontend和backend配置更简洁,生产常用

注意:name字段只能使用大小写字母,数字,‘-’(dash),’_‘(underscore),’.’ (dot)和 ‘:'(colon),并且严格区分大小写

负载均衡(3)_第9张图片

Proxies配置-defaults

  • defaults 配置参数
option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发
option abortonclose #当服务器负载很高时,自动结束掉当前队列处理比较久的链接,针对业务情况选择开启
option http-keep-alive #开启与客户端的会话保持
option forwardfor #透传客户端真实IP至后端web服务器
mode http|tcp #设置默认工作类型,使用TCP服务器性能更好,减少压力
timeout http-keep-alive 120s #session 会话保持超时时间,此时间段内会转发到相同的后端服务器
timeout connect 120s #客户端请求从haproxy到后端server最长连接等待时间(TCP连接之前),默认单位ms
timeout server 600s #客户端请求从haproxy到后端服务端的请求处理超时时长(TCP连接之后),默认单位ms,如果超时,会出现502错误,此值建议设置较大些,访止502错误
timeout client 600s #设置haproxy与客户端的最长非活动时间,默认单位ms,建议和timeout server相同
timeout check 5s #对后端服务器的默认检测超时时间
default-server inter 1000 weight 3 #指定后端服务器的默认设置

Proxies配置-frontend

  • frontend 配置参数
bind: #指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中

#格式:
bind [<address>]:<port_range> [, ...] [param*]

#注意:如果需要绑定在非本机的IP,需要开启内核参数:net.ipv4.ip_nonlocal_bind=1
  • 范例
listen http_proxy #监听http的多个IP的多个端口和sock文件
	bind :80,:443,:8801-8810
	bind 10.0.0.1:10080,10.0.0.1:10443
	bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy

listen http_https_proxy #https监听
	bind :80
	bind :443 ssl crt /etc/haproxy/site.pem #公钥和私钥公共文件

listen http_https_proxy_explicit #监听ipv6、ipv4和unix sock文件
	bind ipv6@:80
	bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
	bind [email protected] user root mode 600 accept-proxy

listen external_bind_app1 #监听file descriptor
	bind "fd@${FD_APP1}"
  • 生产示例
frontend web_port #可以采用后面形式命名:业务-服务-端口号
	bind :80,:8080
	bind 10.0.0.7:10080,:8801-8810,10.0.0.17:9001-9010
	mode http|tcp #指定负载协议类型
	use_backend <backend_name> #调用的后端服务器组名称

Proxies配置-backend

  • 定义一组后端服务器,backend服务器将被frontend进行调用。
mode 	http|tcp 	#指定负载协议类型,和对应的frontend必须一致
option 		#配置选项
server 		#定义后端real server

注意:option后面加 httpchk,smtpchk,mysql-check,pgsql-check,ssl-hello-chk方法,可用于实现更多应用层检测功能。

option 配置

check #对指定real进行健康状态检查,如果不加此设置,默认不开启检查
	addr <IP> #可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
	port <num> #指定的健康状态监测端口
	inter <num> #健康状态检查间隔时间,默认2000 ms
	fall <num> #后端服务器从线上转为线下的检查的连续失效次数,默认为3
	rise <num> #后端服务器从下线恢复上线的检查的连续有效次数,默认为2
weight <weight> #默认为1,最大值为256,0表示不参与负载均衡,但仍接受持久连接
backup #将后端服务器标记为备份状态,只在所有非备份主机down机时提供服务,类似Sorry Server
disabled #将后端服务器标记为不可用状态,即维护状态,除了持久模式,将不再接受连接
redirect prefix http://www.baidu.com/ #将请求临时(302)重定向至其它URL,只适用于http模式
redir http://www.baidu.com #将请求临时(302)重定向至其它URL,只适用于http模式
maxconn <maxconn> #当前后端server的最大并发连接数
backlog <backlog> #当前端服务器的连接数达到上限后的后援队列长度,注意:不支持backend

frontend+backend配置实例

负载均衡(3)_第10张图片

  • node1和node2搭建一个网站
[root@node1 ~]# yum -y install httpd
[root@node1 ~]# echo "node1 ..." > /var/www/html/index.html
[root@node1 ~]# systemctl start httpd
[root@node1 ~]# systemctl enable httpd
  • haproxy配置文件
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
global
	maxconn 100000
	chroot /apps/haproxy
	stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
	#uid 99
	#gid 99
	user haproxy
	group haproxy
	daemon
	#nbproc 4
	#cpu-map 1 0
	#cpu-map 2 1
	#cpu-map 3 2
	#cpu-map 4 3
	pidfile /var/lib/haproxy/haproxy.pid
	log 127.0.0.1 local2 info

defaults
	option http-keep-alive
	option forwardfor
	maxconn 100000
	mode http
	timeout connect 300000ms
	timeout client 300000ms
	timeout server 300000ms

listen stats
	mode http
	bind 0.0.0.0:9999
	stats enable
	log global
	stats uri /haproxy-status
	stats auth admin:123456

frontend test-http
	bind :80
	mode tcp
	use_backend test-http-nodes

backend test-http-nodes
	mode tcp
	default-server inter 1000 weight 6
	server web1 192.168.175.20:80 check inter 3000 fall 3 rise 5 weight 2 addr 192.168.175.20 port 3306
	server web2 192.168.175.30:80 check inter 3000 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy
  • 验证结果
    负载均衡(3)_第11张图片

  • 因为检查node1的3306接口并没有启动,所以node1始终是down的
    负载均衡(3)_第12张图片

  • 装个数据库。试一下开启3306之后会不会正常

[root@haproxy ~]# yum install -y mariadb-server
[root@haproxy ~]# systemctl start mariadb
[root@haproxy ~]# mysqladmin password '123456'
打开之后看健康检测就正常了,可以正常进行负载均衡

listen替代frontend+backend

使用listen替换上面的frontend和backend的配置方式,可以简化设置,通常只用于TCP协议的应用

listen WEB_PORT_80
	bind :80
	mode http
	option forwardfor
	server web1 192.168.175.20:80 check inter 3000 fall 3 rise 5
	server web2 192.168.175.30:80 check inter 3000 fall 3 rise 5

[root@haproxy ~]# systemctl restart haproxy

使用子配置文件保存配置

​ 当业务众多时,将所有配置都放在一个配置文件中,会造成维护困难。可以考虑按业务分类,将配置信息拆分,放在不同的子配置文件中,从而达到方便维护的目的。

  • 创建子配置目录
[root@haproxy ~]# mkdir /etc/haproxy/conf.d/
  • 创建子配置文件,注意:必须为cfg后缀
[root@haproxy ~]# vim /etc/haproxy/conf.d/test.cfg
listen WEB_PORT_80
	bind :80
	mode http
	option forwardfor
	balance roundrobin
	server web1 192.168.175.20:80 check inter 3000 fall 3 rise 5
	server web2 192.168.175.30:80 check inter 3000 fall 3 rise 5
  • 添加子配置目录到unit文件中
[root@haproxy ~]# vim /lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

删掉主配置文件里的listen web_port否则会冲突
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl daemon-reload
[root@haproxy ~]# systemctl restart haproxy

五、HAProxy调度算法

HAProxy通过固定参数 balance 指明对后端服务器的调度算法,该参数可以配置在listen或backend选项中。

HAProxy的调度算法分为静态和动态调度算法,但是有些算法可以根据参数在静态和动态算法中相互转换。

官方文档:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4-balance

静态算法

静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和响应速度等,且无法实时修改权重,只能靠重启HAProxy生效。

static-rr

static-rr:基于权重的轮询调度,不支持权重的运行时利用socat进行动态调整及后端服务器慢启动,其后端主机数量没有限制,相当于LVS中的 wrr

listen web_host
	bind :80
	mode http
	log global
	balance static-rr
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 2 check inter 3000 fall 2 rise 5

测试访问效果,同时运行下面命令,观察结果

while true;do curl http://192.168.175.10/index.html ; sleep 0.1;done

first

first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少

listen web_host
	bind :80
	mode http
	log global
	balance first
	server web1 192.168.175.20:80 maxconn 2 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

动态算法

​ 动态算法:基于后端服务器状态进行调度适当调整,优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。

roundrobin

roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不同于lvs中的rr轮询模式,HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server,支持对real server权重动态调整,roundrobin为默认调度算法

listen web_host
	bind :80
	mode http
	log global
	balance roundrobin
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 2 check inter 3000 fall 2 rise 5

支持动态调整权重

# 对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个强大的多功能的网络工具,Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式,如IP,TCP,UDP,IPv6,pipe,exec,system,open,proxy,openssl,socket等。
# 使用Socat工具修改时 这行配置文件stats socket /var/lib/haproxy/stats mode 600 level admin 这里要指定为admin,否则可能socat会有权限错误
# echo "get weight WEB_PORT_80/web1" | socat stdio /var/lib/haproxy/haproxy.sock #weight WEB_PORT_80/web1这里是和配置文件对应的
1 (initial 1)
# echo "set weight web_host/web1 3" | socat stdio /var/lib/haproxy/haproxy.sock

# echo "get weight web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock
3 (initial 1)

leastconn

leastconn加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度(新客户端连接),比较适合长连接的场景使用,比如:MySQL等场景。

listen web_host
	bind :80
	mode http
	log global
	balance leastconn
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

random

​ 在1.9版本开始增加一个叫做random的负载平衡算法,其基于随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用,支持weight的动态调整,weight较大的主机有更大概率获取新请求

listen web_host
	bind :80
	mode http
	log global
	balance random
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

其他算法

其它算法即可作为静态算法,又可以通过选项成为动态算法

source

源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项更改

这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景

源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash

map-base取模法

map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法

所谓取模运算,就是计算两个数相除之后的余数,10%7=3, 7%4=3 map-based算法:基于权重取模,hash(source_ip)%所有后端服务器相加的总权重

listen web_host
	bind :80
	mode tcp
	log global
	balance source
	hash-type map-based
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 3
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 3
	
[root@haproxy ~]#echo "set weight web_host/192.168.175.20 10" | socat stdio /var/lib/haproxy/haproxy.sock
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.

[root@haproxy ~]#echo "set weight web_host/192.168.175.20 0" | socat stdio /var/lib/haproxy/haproxy.sock

[root@haproxy conf.d]#echo "get weight web_host/192.168.175.20" | socat stdio /var/lib/haproxy/haproxy.sock
0 (initial 1)

一致性hash

一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,hash(o)mod n ,该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动

1、key1=hash(source_ip)%(2^32) [0—4294967295]

2、keyA=hash(后端服务器虚拟ip)%(2^32)

3、将key1和keyA都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器

listen web_host
	bind :80
	mode tcp
	log global
	balance source
	hash-type consistent
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器,适用于后端是缓存服务器场景,默认是静态,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash。

注意:此算法是应用层,所有只支持 mode http ,不支持 mode tcp

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#
左半部分:/<path>;<params>
整个uri:/<path>;<params>?<query>#
  • uri 取模法配置示例
listen web_host
	bind :80
	mode http
	log global
	balance uri
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5
  • uri 一致性hash配置示例
listen web_host
	bind :80
	mode http
	log global
	balance uri
	hash-type consistent
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

url_param

url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server,如果无没key,将按roundrobin算法

假设:
url = http://www.test.com/foo/bar/index.php?key=value

则:
host = "www.test.com"
url_param = "key=value"
  • url_param取模法配置示例
listen web_host
	bind :80
	mode http
	log global
	balance url_param userid #url_param hash
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5
  • url_param一致性hash配置示例
listen web_host
	bind :80
	mode http
	log global
	balance url_param userid #对url_param的值取hash
	hash-type consistent
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

hdr

针对用户每个http头部(header)请求中的指定信息做hash,此处由 name 指定的http首部将会被取出并做hash计算,然后由服务器总权重取模以后派发至某挑出的服务器,如无有效的值,则会使用默认的轮询调度。

  • hdr取模法配置示例
listen web_host
	bind :80
	mode http
	log global
	balance hdr(User-Agent)
	#balance hdr(host)
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5
  • 一致性hash配置示例
listen web_host
	bind :80
	mode http
	log global
	balance hdr(User-Agent)
	hash-type consistent
	server web1 192.168.175.20:80 weight 1 check inter 3000 fall 2 rise 5
	server web2 192.168.175.30:80 weight 1 check inter 3000 fall 2 rise 5

rdp-cookie

rdp-cookie对远windows远程桌面的负载,使用cookie保持会话,默认是静态,也可以通过hashtype指定map-based和consistent,来定义使用取模法还是一致性hash。

  • rdp-cookie取模法配置示例
listen RDP
	bind :3389
	balance rdp-cookie
	mode tcp
	server rdp0 192.168.175.20:3389 check fall 3 rise 5 inter 2000 weight 1
  • rdp-cookie一致性hash配置示例
[root@haproxy ~]#cat /etc/haproxy/conf.d/windows_rdp.cfg
listen magedu_RDP_3389
	bind 172.16.0.100:3389
	balance rdp-cookie
	hash-type consistent
	mode tcp
	server rdp0 10.0.0.200:3389 check fall 3 rise 5 inter 2000 weight 1

[root@haproxy ~]#hostname -I
10.0.0.100 172.16.0.100

算法总结

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
rdp-cookie-------->tcp

各算法使用场景

first #使用较少

static-rr #做了session共享的web集群
roundrobin
random

leastconn #数据库
source #基于客户端公网IP的会话保持

uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http

hdr #基于客户端请求报文头部做下一步处理

rdp-cookie #很少使用

六、HAProxy状态页

通过web界面,显示当前HAProxy的运行状态

官方帮助:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4-stats%20admin

  • 状态页配置项
stats enable #基于默认的参数启用stats page
stats hide-version #将状态页中haproxy版本隐藏
stats refresh <delay> #设定自动刷新时间间隔,默认不自动刷新
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats realm <realm> #账户认证时的提示信息,示例:stats realm HAProxy\Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication,可有多行用户
stats admin { if | unless } <cond> #启用stats page中的管理功能
  • 启用状态页
listen stats
	bind :9999
	stats enable
	#stats hide-version
	stats uri /haproxy-status
	stats realm HAPorxy\ Stats\ Page
	stats auth haadmin:123456 #两个用户
	stats auth admin:123456
	#stats refresh 30s
	stats admin if TRUE #安全原因,不建议打开
  • 状态页信息
pid = 27134 (process #1, nbproc = 1, nbthread = 1) #pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
uptime = 0d 0h00m04s #启动了多长时间
system limits: memmax = unlimited; ulimit-n = 200029 #系统资源限制:内存/最大打开文件数/
maxsock = 200029; maxconn = 100000; maxpipes = 0 #最大socket连接数/单进程最大连接数/最大管道数maxpipes
current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000kbps #当前连接数/当前管道数/当前连接速率
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 or backup DOWN for maintenance (MAINT) #active或者backup服务器人为下线的
active or backup SOFT STOPPED for maintenance #active或者backup被人为软下线(人为将weight改成0)

负载均衡(3)_第13张图片

backend server信息

session rate(每秒的连接会话信息): Errors(错误统计信息):
cur:每秒的当前会话数量 Req:错误请求量
max:每秒新的最大会话数量 conn:错误链接量
limit:每秒新的会话限制量 Resp:错误响应量
sessions(会话信息): Warnings(警告统计信息):
cur:当前会话量 Retr:重新尝试次数
max:最大会话量 Redis:再次发送次数
limit: 限制会话量
Total:总共会话量 Server(real server信息)
LBTot:选中一台服务器所用的总时间 Status:后端机的状态,包括UP和DOWN
Last:和服务器的持续连接时间 LastChk:持续检查后端服务器的时间
Wght:权重
Bytes(流量统计): Act:活动链接数量
In:网络的字节输入总量 Bck:备份的服务器数量
Out:网络的字节输出总量 Chk:心跳检测时间
Dwn:后端服务器连接后都是DOWN的数量
Denied(拒绝统计信息): Dwntme:总的downtime时间
Req:拒绝请求量 Thrtle:server 状态
Resp:拒绝回复量

七、利用状态页实现haproxy服务器的健康性检查

  • 通过curl 命令对haproxy的状态页的访问实现健康检查
[root@haproxy ~]# curl -I http://admin:[email protected]:9999/haproxy-status
HTTP/1.1 200 OK
cache-control: no-cache
content-type: text/html

[root@haproxy ~]# curl -I -u admin:123456 http://192.168.175.10:9999/haproxystatus
HTTP/1.1 200 OK
cache-control: no-cache
content-type: text/html

你可能感兴趣的:(负载均衡,运维,HAProxy)