1.负载均衡
负载均衡是一种将网络流量或计算任务分配到多个服务器、计算资源或网络链路上的技术,能优化资源使用、最大化吞吐量、最小化响应时间,并避免任何单一资源的过载。
1.1负载均衡的作用
- 提高可用性:能在某台服务器故障时,将其的业务自动转移到其他正常运行的服务器上
- 提高性能:能将请求分散到多台服务器上
- 优化资源利用率:能节省公网IP地址,动态分配资源
- 提高安全性:能隐藏内部服务器IP
1.2负载均衡的类型
1.2.1基于硬件
- F5
- Citrix NetScaler
- Radware Alteon
- Array
- AD-1000
1.2.2基于网络层
- 四层负载均衡:基于传输层(TCP/UDP)的信息(IP/PORT)进行流量分配
- 七层负载均衡:基于应用层(HTTP、HTTPS等协议)的内容进行流量分配
特性 | 四层 | 七层 |
---|---|---|
层级 | 传输层(TCP/UDP) | 应用层(HTTP/HTTPS) |
依据 | IP、PORT | URL、Cookie、内容、头部 |
速度 | 快 | 较慢 |
协议支持 | TCP、UDP、ICMP | HTTP、HTTPS、FTP、SMTP |
软件支持 | LVS、Nginx、HAproxy | Nginx、HAproxy |
2.HAproxy
HAproxy是高性能的开源负载均衡器和代理服务器,具有负载均衡、流量控制、安全、高可用、监控等功能。
2.1配置及信息
2.1.1配置
#HAproxy:
# 安装
dnf install haproxy -y
# 查看安装信息
haproxy -v
#RS1、RS2:
# 安装Nginx
dnf install Nginx -y
2.1.2信息
软件信息
- 启动文件: /lib/systemd/system/haproxy.service
- 主配置目录:/etc/haproxy/
- 主配置文件: /etc/haproxy/haproxy.cfg
- 子配置目录:/etc/haproxy/conf.d
配置文件信息
global # 全局配置 - 定义全局参数
log 127.0.0.1 local2 # 日志
chroot /var/lib/haproxy # 安全隔离目录
pidfile /var/run/haproxy.pid # PID文件位置
maxconn 4000 # 每个进程最大连接数
maxconnrate 100 # 指定每个客户端每秒建立连接的最大数量
user haproxy # 运行用户
group haproxy # 运行组
daemon # 以守护进程方式运行
# turn on stats unix socket
stats socket /var/lib/haproxy/stats # 指定haproxy的套接字文件
# nbproc与nbthread互斥
nbproc 2 # 指定haproxy的work进程数量,默认1
nbthread 2 # 指定haproxy的线程数量,默认1
cpu-map 1 0 # 指定work绑定的cpu核心
cpu-map 2 1 # 指定work绑定的cpu核心
# SSL优化配置
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
defaults # 默认配置 - 为其他段提供默认值
mode http # 默认模式(http|tcp)
log global # 继承全局日志配置
option httplog # 记录HTTP日志
option dontlognull # 不记录空连接
option http-server-close # 启用HTTP连接关闭优化
option forwardfor except 127.0.0.0/8 # 添加X-Forwarded-For头
option redispatch # 连接失败时重试其他服务器
retries 3 # 后端服务器重试次数
timeout http-request 10s # HTTP请求超时
timeout queue 1m # 队列超时
timeout connect 10s # 连接超时
timeout client 1m # 客户端超时
timeout server 1m # 服务器超时
timeout http-keep-alive 10s # HTTP Keep-Alive超时
timeout check 10s # 健康检查超时
errorfile 503 /etc/haproxy/errorpages/503.http #自定义错误页面
# proxies配置
frontend [name] # 前端服务配置 - 定义客户端连接处理
backend [name] # 后端配置段 - 定义服务器池和负载均衡
listen [name] # 监听配置段 - 结合前后端的简化配置
listen stats # HAproxy状态页配置
多进程与多线程
# 多进程
# 在global配置nbproc参数,再cpu-map绑定work和cpu
nbproc 2
cpu-map 1 0
cpu-map 2 1
# 多线程
# 在global配置nbthread参数即可
nbthread 2
2.1.3proxies配置
default配置
#运行模式
mode http #连接协议
#日志
log global #继承全局的日志目录
option httplog #记录http相关日志
option dontlognull #不记录空会话连接日志
#option相关
option http-server-close #保持客户端连接开启但关闭服务器端连接
option forwardfor except 127.0.0.0/8 #添加 X-Forwarded-For 头
option redispath #连接失败时重新分发请求
option http-keep-alive #开启与客户端的会话保持
#超时设置
timeout http-request 10s #HTTP 请求完成超时时间
timeout queue 1m #请求在队列中的最大等待时间
timeout connect 120s #连接后端服务器的超时时间
timeout client 600s #客户端不活动超时时间
timeout server 600s #服务器端不活动超时时间
timeout http-keep-alive 60s #session 会话保持超时时间,此时间段内会转发到相同的后端服务器
timeout check 10s #指定后端服务器健康检查的超时时间
frontend配置
frontend <name>
bind <指定haproxy监听的ip地址>:<port> [参数]
mode <http/tcp>
default_backend <后端名称>
frontend WebServer
bind 192.168.0.200:80
mode http
default_backend webserver_RS
beckend配置
backend <名称>
mode <http/tcp>
balance <算法>
server <名称> <ip地址>:<端口> [参数]
#server参数
check #启用健康检查
maxconn #最大并发连接数
backup #标记为备份服务器
weight #权重值
cookie #指定持久性cookie值
ssl #启用SSL/TLS连接到后端
inter <num> #健康状态检查间隔时间,默认2000 ms
fall <num> #后端服务器从线上转为线下的检查的连续失效次数,默认为3
rise <num> #后端服务器从下线恢复上线的检查的连续有效次数,默认为2
disabled #将后端服务器标记为不可用状态
backend Webserver_RS
mode http
server web1 192.168.0.210:80 check inter 3s fall 3 rise 5 weight 5
server web2 192.168.0.220:80 check inter 3s fall 3 rise 5
listen配置
listen WebServer
bind 192.168.0.200:80
mode http
option forwardfor
server web1 192.168.0.210:80 check inter 3s fall 3 rise 5 weight 5
server web2 192.168.0.220:80 check inter 3s fall 3 rise 5
2.2socat工具
Socat (SOcket CAT) 是一个功能强大的网络工具,可以看作是 netcat 的增强版,它能够在两个数据流之间建立双向通道,支持多种协议和连接方式。
功能:
- 动态修改服务器权重
stats soket /var/lib/haproxy/stats mode 600 level admin
echo "set weight WebServer/web1 10" | socat stdio /var/lib/haproxy/stats
3.haproxy的算法
3.1静态
static-rr 轮询
- 不支持动态调整
- 不支持端服务慢启动
first
- 选择第一个可用的服务器直到其满负荷
- 忽略服务器的权重设置
3.2动态
roundrobin 权重轮询
- 支持动态调整权重
- 支持慢启动
- 默认算法
leastconn 最少连接
- 将新连接分配给当前连接数最少的服务器
- 适用于长连接场景
- 支持权重的运行时调整和慢启动
3.3可调整
调整 “ hash-type consistent” 参数决定取模法(map-based/静态/默认)还是一致性hash(consistent/动态)
- 取模法
- 服务器号 = hash(key) % 服务器数量
- hash:对请求的关键字(如用户ID、源IP等)进行哈希计算
- 将哈希结果对服务器数量取模,根据模值确定目标服务器
- 不适合用作动态算法的计算方式
- 一致性hash
- 哈希环:将哈希空间组织成环形(0 ~ 2^32-1),对每个服务器节点计算多个哈希值(虚拟节点),分布在环上
- 对请求关键字哈希,在环上顺时针查找第一个≥该哈希值的节点
source 源IP哈希
- 根据客户端源IP地址哈希分配,保持同一客户端访问同一服务器
- 适用于session会话保持但不支持cookie和缓存的场景
uri
- 基于应用层,所以只支持 mode http
- 根据用户URI的左半部分或整个uri做hash
- 适用于后端是缓存服务器场景
url_param
- 能选择用户url中的参数的值参与hash计算
- 用于需要基于特定参数保持的会话
hdr
- 根据http头部的信息做hash
- 无有效值,则会使用默认的轮询调度
4.其他功能
4.1基于cookie的会话保持
在backend或listen中配置
backend/listen
cookie <name> [参数]
#参数
#操作模式,三选一
insert #由HAProxy插入Cookie
rewrite #重写已有cookie
prefix #在现有cookie前添加前缀
#行为控制
indirect #服务器响应时不修改Cookie
noache #禁止缓存带有此Cookie的响应
postonly #仅对POST请求插入cookie
preserve #尽可能保留原cookie
#安全
httponly #标记Cookie为仅HTTP访问
secure #指定Cookie仅在HTTPS加密连接中传输,不会通过未加密的HTTP协议发送
#作用域控制
domain #设置cookie作用域
#过期时间
maxidle #空闲超时时间s
maxlife #绝对生存时间s
vim /etc/haproxy/haproxy.cfg
listen WebServer1
bind 172.25.254.200:80
option forwardfor
mode http
balance roundrobin
cookie WebCookie insert nocache indirect
server web1 192.168.0.210:80 check inter 3s fall 3 rise 5 weight 5
server web2 192.168.0.220:80 check inter 3s fall 3 rise 5 weight 5
4.2haproxy的状态页
#配置项
stats enable #基于默认的参数启用stats page
stats hide-version #隐藏haproxy版本
stats refresh <> #自动刷新时间间隔
stats uri <> #自定义stats page uri
stats auth <username>:<password> #认证配置
stats admin {if | unless} <> #启用page的管理功能
listen stats
mode http
bind *:8888
stats enable
log global
stats uri /stats
stats auth li:123
4.3IP透传
用于获取客户端的真实真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景
4.3.1四层IP透传
#在nginx配置文件的http配置的log_format main后添加"$proxy_protocol_addr"
#在nginx配置文件的server配置的listen后添加proxy_protocol,设置只能透过底层代理访问此网站
vim /etc/nginx/nginx.conf
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
' "$proxy_protocol_addr"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 80 proxy_protocol;
}
}
#修改haproxy配置文件,mode走四层设置为tcp
vim /etc/haproxy/haproxy.cfg
listen WebServer
mode tcp
bind 172.25.254.200:80
balance roundrobin
server web1 172.25.254.210:80 send-proxy
4.3.2七层IP透传
#haproxy配置
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
[ except <network> ] #请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
[ header <name> ] #使用自定义的首部名称,而非“X-Forwarded-For"
[ if-none ] #如果没有首部才添加首部,如果有使用默认值
listen WebServer
option forwardfor []
mode http
balance ……
server ……
4.4ACL
访问控制列表ACL是一种基于包过滤的访问控制技术。它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配)即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。
ACL要配置在frontend中,所以不使用listen
frontend ACL
bind *:80
mode http
acl <aclname> <匹配规范> [匹配模式] [操作符] <匹配内容>
acl_name:
1.可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线
2.严格区分大小写
4.4.1匹配规则
#hdr类,HTTP 头部匹配
hdr([name]) #匹配 请求头 的完整值(严格匹配)
hdr_ip([name]) #匹配 IP 地址类请求头
hdr_val([name]) #提取请求头的 数值 进行比较
hdr_beg([name]) = hdr([name]) -m beg = hdr_dom([name]) -m beg = hdr([name]) -m beg #前缀匹配
hdr_end = hdr -m end #后缀匹配
hdr_dom #匹配域名类头部
hdr_sub = hdr -m sub #子串匹配
hdr_reg = hdr -m reg #正则匹配
hdr_len #检查头部值的长度
hdr_dir #匹配头部的uri路径
#path类,URL 路径匹配
path <路径> #匹配完整的请求路径(不包括查询参数)
path_beg #匹配以指定字符串开头的路径
path_end #匹配以指定字符串结尾的路径
path_sub #匹配包含指定子串的路径
path_reg #正则匹配路径
path_dir #匹配路径中的目录部分
#url类,URL 参数匹配
url <> #匹配包括协议、主机、路径和查询参数的完整URL(需解码后匹配)
url_beg #匹配以指定字符串开头的URL
url_end #匹配以指定字符串结尾的URL
url_sub #匹配包含指定子串的URL
url_reg #正则匹配URL
url_param #查询参数匹配
url_port #URL端口匹配
url_scheme #协议匹配
#base类,用于匹配请求的基础属性
base <> #匹配请求的基础信息(包括方法和路径)
base_beg #匹配以指定字符串开头的基础信息
base_end #匹配以指定字符串结尾的基础信息
base_sub #匹配包含指定子串的基础信息
base_reg #使用正则匹配基础信息
base_len #基础信息长度
base32/base64 #编码匹配
base_uri #基础URI匹配
acl exact_match hdr(User-Agent) "Mozilla/5.0"
acl is_aws hdr(User-Agent) -m beg "aws-sdk-" # 匹配以 aws-sdk- 开头的 UA
acl is_image hdr(Content-Type) -m end image/jpeg # 匹配 JPEG 类型
acl has_mobile hdr(User-Agent) -m sub "Mobile" # 包含 Mobile 字符串
acl is_uuid hdr(X-Request-ID) -m reg [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
acl valid_auth hdr_len(Authorization) eq 32 # 固定长度的 Token
acl case_sensitive hdr(X-Custom-Header) -m str "ExactValue" # 大小写敏感
acl case_insensitive hdr(X-Custom-Header) -i "anycase" # 忽略大小写
acl exact_path path /api/users # 只匹配 /api/users
acl api_path path_beg /api/ # 匹配 /api/、/api/users
acl static_path path_beg /static/ /images/ # 多前缀匹配
acl img_path path_end .jpg .png # 匹配 /pic.jpg、/a/b.png
acl version_path path_sub /v2/ # 匹配 /api/v2/users、/v2/docs
acl id_path path_reg ^/users/[0-9]+$ # 匹配 /users/123
acl admin_dir path_dir /admin/ # 匹配 /admin/、/admin/users
acl exact_url url https://example.com/api?version=1
acl cdn_url url_beg https://cdn. # 匹配所有CDN开头的URL
acl pdf_url url_end .pdf # 匹配所有PDF文件URL
acl tracking_url url_sub /track/ # 匹配包含/track/的URL
acl uuid_url url_reg [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
acl has_token url_param(token) -m found # 检查token参数是否存在
acl valid_id url_param(id) -m reg ^[0-9]+$ # ID必须是数字
4.4.2匹配模式
-i 不区分大小写
-m 使用指定的正则表达式匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系
4.4.3组合ACL调用方式
- 与:默认使用,空格
- 或:or 或 ||
- 否定:!
4.5haproxy错误界面
haproxy默认错误界面
/usr/share/haproxy/400.http
/usr/share/haproxy/403.http
/usr/share/haproxy/408.http
/usr/share/haproxy/500.http
/usr/share/haproxy/502.http
/usr/share/haproxy/503.http
/usr/share/haproxy/504.http
4.5.1 haproxy自定义错误页面
#自定义错误页面语句
HTTP/1.0 503 Service Unavailable
Cache-Control:no-cahce
Connection:close
Content-Type:text/html;charset=UTF-8
#在haproxy.cfg的defaults下编辑
errorfile <错误代码> <错误页面文件绝对路径>
#错误页面文件后缀建议为.http与其他html文件区分
defaults
mode http
……
errorfile 503 /haproxy/errorpages/503.http
4.5.2基于http重定向错误页面
#语句
errorloc <错误代码> <URL>
#haproxy.cfg下的defaults
defaults
mode http
……
errorloc 503 https://3.14.com
4.6haproxy四层负载
一般做tcp协议应用:MySQL、Redis、Memcache、RabbitMQ
listen mdb
bind 172.25.254.200:3306
mode tcp
balance roundrobin
server mdb1 172.25.254.210:3306 check
server mdb2 172.25.254.220:3306 check
frontend mdb
bind *:3306
mode tcp
use_backend mdb_rs
backend mdb_rs
mode tcp
balance roundrobin
server mdb1 172.25.254.210:3306 check
server mdb2 172.25.254.220:3306 check
4.7haproxy https 实现
#做证书
mkdir /etc/haproxy/certs
openssl req -newkey rsa:2048 -nodes -sha256 –keyout /etc/haproxy/certs/user1.key -x509 -days 365 -out /etc/haproxy/certs/user1.crt
#https配置
vim /etc/haproxy/haproxy.cfg
frontend WebServer
bind *:80
redirect scheme https if !{ ssl_fc }
mode http
use_backend WebCluster
frontend WebServer-https
bind *:443 ssl crt /etc/haproxy/timinglee.org.pem
mode http
use_backend webcluster
backend WebCluster
mode http
balance roundrobin
server web1 172.25.254.210:80 check inter 3s fall 3 rise 5
server web2 172.25.254.220:80 check inter 3s fall 3 rise 5