Appearance
负载均衡概述
应用场景: web服务器有多台的情况,用户请求尽可能平 均分布在web上
负载均衡 | 说明 | 应用集建议 |
---|---|---|
开源软件 | nginx(web,负载,缓存) tengine,openresty(lua) haproxy(专门负载均衡) | 主要使用,使用简单. 也是主要使用,专用负载均衡. 负载均衡功能比ngx |
lvs(专门负载均衡,性能高) | 高并发场景,20w,30w并发. 性能好,维护较为复杂. | |
硬件负载均衡 | F5(收购nginx) | 成本高,最好成对 |
Ngx负载均衡极速上手指南
环境准备
web01,02 分别配置
shell
[root@web02 /app/code/lb]# cat /etc/nginx/conf.d/default.conf
server{
listen 80;
server_name lb.oldboylinux.cn;
root /app/code/lb/;
location / {
index index.html;
}
}
[root@web02 /app/code/lb]# cat index.html
web02 lb.oldboylinux.cn
[root@web01 /app/code/lb]# cat index.html
web01 lb.oldboylinux.cn
systemctl restart nginx
查看是否正常nginx t-
shell
[root@web02 /app/code/lb]# curl -H Host:lb.oldboylinux.cn 10.0.0.7
web01 lb.oldboylinux.cn
[root@web02 /app/code/lb]# curl -H Host:lb.oldboylinux.cn 10.0.0.8
web02 lb.oldboylinux.cn
lb 接入负载均衡
shell
# 下面是将原配置合并成一段代码,并在代码内部添加详细解释的版本
# 此配置用于将请求转发到后端服务器,实现负载均衡功能
# 定义一个名为 lb_pools 的 upstream 服务器组,包含两台后端服务器
upstream lb_pools {
server 10.0.0.7:80; # 第一个后端服务器的 IP 地址和端口,这里采用默认轮询负载均衡算法
server 10.0.0.8:80; # 第二个后端服务器的 IP 地址和端口
}
server {
listen 80; # 该虚拟主机监听80端口,即 HTTP 默认端口
server_name lb.oldboylinux.cn; # 指定该虚拟主机响应的域名,所有请求此域名的连接将由此 server 块处理
# 以下日志配置项被注释掉了,如有需要可启用来指定错误日志和访问日志的位置
# error_log /path/to/error.log;
# access_log /path/to/access.log;
location / {
# 将所有对根路径(/)的请求代理到上面定义的 lb_pools 服务器组,实现请求的反向代理和负载均衡
proxy_pass http://lb_pools;
# proxy_set_header 指令用于将客户端请求中的关键信息传递到后端服务器
proxy_set_header Host $http_host; # 将原始请求的主机头信息(域名)传递到后端
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 将客户端原真实 IP 地址附加到 X-Forwarded-For 头,用于记录或安全检查
proxy_set_header X-Real-Ip $remote_addr; # 直接将客户端真实 IP 地址通过 X-Real-Ip 头传递给后端服务器
}
}
测试
shell
AAA@DESKTOP-QQVR3OB MINGW64 ~/Desktop
$ curl lb.oldboylinux.cn
web02 lb.oldboylinux.cn
AAA@DESKTOP-QQVR3OB MINGW64 ~/Desktop
$ curl lb.oldboylinux.cn
web01 lb.oldboylinux.cn
AAA@DESKTOP-QQVR3OB MINGW64 ~/Desktop
$ curl lb.oldboylinux.cn
web02 lb.oldboylinux.cn
proxy_set_header 配置指令解释
1. proxy_set_header Host $http_host;
- 作用: 设置HTTP请求头中的Host字段,使其包含原始请求的域名。
- 解释:
$http_host
变量获取客户端请求的原始域名(包括端口,如果指定)。- 如果不设置此头,负载均衡器到Web服务器的请求头中的Host信息可能不正确,导致Web服务使用默认站点处理请求。
- 示例: 如果客户端访问
example.com
,此配置确保后端服务器看到的Host头也是example.com
。
2. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- 作用: 设置X-Forwarded-For头,记录客户端的真实IP地址。
- 解释:
$proxy_add_x_forwarded_for
变量会追加客户端IP到现有的X-Forwarded-For头(如果存在),否则创建新的头。- 多层代理场景: 如果请求经过CDN、负载均衡等多层代理,每个代理都会追加自己的IP到X-Forwarded-For头。最终,最右边的IP是客户端的真实IP。
- 访问日志: 可以通过
$http_x_forwarded_for
获取XFF信息,并写入日志的最后一列。
3. proxy_set_header X-Real-Ip $remote_addr;
- 作用: 设置X-Real-Ip头,直接记录客户端的真实IP地址。
- 解释:
$remote_addr
变量直接获取与Nginx建立连接的客户端IP地址。- 在简单代理场景中,此头可以直接提供客户端的真实IP。
- 注意: 如果经过多层代理,此头可能只记录最后一个代理的IP,而非客户端真实IP。此时应优先使用X-Forwarded-For。
配置示例
nginx
location / {
proxy_pass http://backend;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
}
常见问题
- 为什么需要设置这些请求头?
确保后端服务器能正确识别原始请求的域名和客户端IP,避免安全问题和日志记录错误。 - X-Forwarded-For和X-Real-Ip的区别?
- X-Forwarded-For记录IP链,适用于多层代理环境。
- X-Real-Ip直接记录客户端IP,适用于简单代理场景。
- 如果配置错误会发生什么?
- 后端服务器可能无法正确识别域名,导致返回错误的网站内容。
- 日志中记录的IP地址可能不准确,影响安全审计和流量分析。
负载均衡轮询算法
加权轮询
shell
upstream lb_pools {
server 10.0.0.7:80 weight=1;
server 10.0.0.8:80 weight=3;
}
ip_hash
shell
upstream lb_pools {
ip_hash;
server 10.0.0.7:80 weight=1;
server 10.0.0.8:80 weight=3;
}
url_hash
shell
upstream lb_pools {
hash $request_uri;
server 10.0.0.7:80 weight=1;
server 10.0.0.8:80 weight=3;
}
负载均衡监控upstream_check_module
添加第3方模块,编译安装 nginx.
正常流程:
🅰 下nginx源代码
🅱 下载upstream_check模 块代码
🆎编译安装nginx指定模块 --add-module指定. 最后替换现有的nginx命令. 使用teninge(源码包中自带常用的第3方模块)
下载tengine源码(db01)
shell
[root@lb01 ~]# curl -v 10.0.0.5/status
Active connections: 1
server accepts handled requests request_time
2 2 2 0
Reading: 0 Writing: 1 Waiting: 0
* Connection #0 to host 10.0.0.5 left intact
配置负载均衡文件
shell
# 定义一个名为 lb_pools 的上游服务器组,用于负载均衡
upstream lb_pools {
# 添加两台后端服务器,权重均为3,表示请求将按比例分配
server 10.0.0.7:80 weight=3;
server 10.0.0.8:80 weight=3;
# 配置健康检查参数
# interval=3000:每隔3000毫秒进行一次健康检查
# rise=2:连续2次成功则认为服务器恢复正常
# fall=5:连续5次失败则认为服务器不可用
# timeout=1000:健康检查的超时时间为1000毫秒
# type=http:使用HTTP协议进行健康检查
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
# 指定健康检查时发送的HTTP请求内容
check_http_send "HEAD / HTTP/1.0\r\nHost:lb.oldboylinux.cn\r\n\r\n";
# 指定认为服务器正常的HTTP响应状态码范围
check_http_expect_alive http_2xx http_3xx;
}
# 配置一个服务器块,监听80端口,处理域名为 lb.oldboylinux.cn 的请求
server {
listen 80;
server_name lb.oldboylinux.cn;
# 配置根路径的请求处理
location / {
# 将请求转发到上游服务器组 lb_pools
proxy_pass http://lb_pools;
# 设置转发请求时的头部信息
proxy_set_header Host $http_host; # 保留原始的Host头部
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 添加客户端的真实IP地址
proxy_set_header X-Real-Ip $remote_addr; # 设置客户端的真实IP地址
}
# 配置 /lb_status 路径,用于查看上游服务器的健康状态
location /lb_status {
# 以下三行用于限制访问权限,当前被注释掉
# allow 10.0.0.1; # 允许IP为10.0.0.1的主机访问
# allow 172.16.1.0/24; # 允许IP段为172.16.1.0/24的主机访问
# deny all; # 拒绝所有其他主机访问
# 启用健康检查状态页面
check_status;
}
}
配置完效果 lb.oldboylinux.cn/lb_status
七层负载均衡
概述
七层负载均衡处理的是 HTTP/HTTPS 协议,它在应用层(第七层)对请求进行解析,然后决定如何分发到不同的后端服务器。
特点
- 基于内容:可以基于请求的内容(如 URL、请求头、Cookie 等)进行负载均衡。
- 灵活性高:支持更复杂的负载均衡策略,可以按请求的特定内容进行调度。
- 更高的开销:因为要解析请求内容,处理速度相对四层会稍慢。
举例
shell
# 定义一个名为 'exam_seven_pools' 的上游服务器池,包含两台服务器
upstream exam_seven_pools {
# 定义第一台服务器,监听 80 端口
server 10.0.0.7:80;
# 定义第二台服务器,监听 80 端口
server 10.0.0.8:80;
}
# 配置第一个虚拟主机,处理域名为 adminmax.linuxpath.cn 的请求
server {
listen 80; # 监听 80 端口,处理客户端请求
server_name adminmax.linuxpath.cn; # 配置服务器的域名
location / {
# 将请求转发到 'exam_seven_pools' 上游服务器池
proxy_pass http://exam_seven_pools;
# 设置请求头信息,转发客户端的原始请求头
proxy_set_header Host $http_host; # 保持原始 Host 头部信息
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保持客户端的 IP 地址链
proxy_set_header X-Real-Ip $remote_addr; # 将客户端的真实 IP 地址传递给后端服务器
}
}
# 配置第二个虚拟主机,处理域名为 stumax.linuxpath.cn 的请求
server {
listen 80; # 监听 80 端口,处理客户端请求
server_name stumax.linuxpath.cn; # 配置服务器的域名
location / {
# 将请求转发到 'exam_seven_pools' 上游服务器池
proxy_pass http://exam_seven_pools;
# 设置请求头信息,转发客户端的原始请求头
proxy_set_header Host $http_host; # 保持原始 Host 头部信息
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保持客户端的 IP 地址链
proxy_set_header X-Real-Ip $remote_addr; # 将客户端的真实 IP 地址传递给后端服务器
}
}
四层负载均衡
概述
四层负载均衡主要是基于 TCP 协议的负载均衡。NGINX 在四层负载均衡中处理的是数据包的传输层(TCP),它不关心传输的数据内容,而是基于网络连接进行分发。
特点
- 基于 IP 和端口:四层负载均衡是通过目标的 IP 地址和端口号来决定请求应该发送到哪个后端服务器。
- 性能高:因为不涉及应用层的数据解析,处理速度较快,适合大流量场景。
- 透明性:客户端和服务器之间的连接是直接的,NGINX 只是转发请求,不会干预通信内容。
举例
shell
# ---------- 全局配置 ----------
# 设置 NGINX 进程的运行用户,通常是一个非特权用户
user nginx;
# 设置 NGINX 启动的工作进程数量,auto 表示根据 CPU 核心数自动设置
worker_processes auto;
# 设置错误日志文件的位置及日志级别
error_log /var/log/nginx/error.log notice;
# 设置 NGINX 进程的 PID 文件路径
pid /var/run/nginx.pid;
# ---------- 事件配置 ----------
events {
# 设置每个 worker 进程的最大连接数
worker_connections 1024;
}
# ---------- Stream 模块(四层负载均衡) ----------
stream {
# 定义日志格式,记录流量的基本信息(客户端地址、时间、协议、状态、流量大小等)
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';
# 设置流量访问日志的路径及格式
access_log /var/log/nginx/stream_exam_access_l4.log basic buffer=32k;
# 设置流量错误日志的路径及级别
error_log /var/log/nginx/stream_exam_error.log error;
# 定义一个上游服务器池,包含两个服务器,进行四层负载均衡
upstream exam_pools {
# 定义第一台服务器,监听 8000 端口
server 10.0.0.9:8000;
# 定义第二台服务器,监听 8000 端口
server 10.0.0.10:8000;
# 使用客户端的 IP 地址作为负载均衡的哈希依据,确保同一 IP 的请求始终转发到同一台服务器
hash $remote_addr consistent;
}
# 定义一个 server 块,处理进入的流量
server {
# 监听 8000 端口
listen 8000;
# 将请求转发到上游服务器池 'exam_pools'
proxy_pass exam_pools;
}
}
# ---------- HTTP 模块(保持原有配置不变) ----------
http {
# 引入 MIME 类型文件,确保正确处理文件类型
include /etc/nginx/mime.types;
# 设置默认的文件类型
default_type application/octet-stream;
# 定义 HTTP 日志格式,记录请求的客户端信息、请求内容、响应状态等
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 设置 HTTP 访问日志的路径和格式
access_log /var/log/nginx/access.log main;
# 启用高效的文件传输模式
sendfile on;
# 设置长连接超时时间(单位为秒)
keepalive_timeout 65;
# 允许或禁用 GZIP 压缩
# gzip on;
# 引入其他配置文件,允许动态加载 .conf 文件中的配置
include /etc/nginx/conf.d/*.conf;
}
四层负载均衡 vs 七层负载均衡
0. 总结
特性 | 四层负载均衡 | 七层负载均衡 |
---|---|---|
工作层 | 传输层(TCP/UDP) | 应用层(HTTP/HTTPS) |
关注内容 | IP 地址、端口号 | 请求路径、请求头、请求方法、Cookie 等 |
适用场景 | 非 HTTP 协议(如数据库、TCP 服务等) | Web 应用、API 服务 |
负载均衡算法 | 基于 IP 地址、端口号,支持哈希、轮询等 | 基于请求内容,可以根据路径、请求头等定制 |
配置复杂度 | 配置简单 | 配置复杂,需处理请求内容 |
性能 | 处理速度快,适用于高吞吐量、大流量的服务 | 解析请求内容稍有开销,适用于灵活的路由需求 |
灵活性 | 灵活性较低 | 高度灵活,支持复杂的路由控制 |
1. 协议层
- 四层负载均衡:
- 工作在 传输层(TCP/UDP)。
- 仅关注数据包的 IP 地址 和 端口号。
- 不会解析传输的数据内容。
- 七层负载均衡:
- 工作在 应用层(HTTP/HTTPS)。
- 解析 请求内容(如 URL、请求头、Cookie 等)。
- 根据应用层的内容做决策,能实现更细粒度的流量控制。
2. 适用场景
- 四层负载均衡:
- 适用于 非 HTTP 协议 或 不需要解析请求内容 的场景,例如数据库负载均衡、TCP 服务的负载均衡等。
- 适合大规模的流量转发,对请求内容无特定要求的场景。
- 七层负载均衡:
- 适用于 Web 应用层的流量,如 HTTP/HTTPS 请求。
- 适合需要基于 URL、请求头、请求方法、Cookie 等内容进行路由和负载均衡的场景。
3. 负载均衡算法
- 四层负载均衡:
- 基于 源 IP 地址(一致性哈希等)或 端口号 来进行流量分发。
- 常见算法:轮询、最少连接、一致性哈希等。
- 七层负载均衡:
- 可以基于 请求内容(如请求路径、请求头、User-Agent、Cookie)来进行路由。
- 更灵活,能够处理复杂的路由规则和请求定制。
4. 配置复杂度
- 四层负载均衡:
- 配置较为简单,通常只需要设置
listen
和proxy_pass
,并选择一个基本的负载均衡算法。 - 例子:
proxy_pass
可以直接使用上游池名称。
- 配置较为简单,通常只需要设置
- 七层负载均衡:
- 配置稍微复杂,因为涉及到对请求内容的解析和细粒度控制。
- 配置项更多,例如
proxy_set_header
用于转发请求头信息,location
用于路径匹配等。
5. 性能
- 四层负载均衡:
- 因为不解析应用层数据,处理速度较快,适用于大流量、低延迟的场景。
- 适合处理 高吞吐量 的服务,性能较好。
- 七层负载均衡:
- 需要解析 HTTP 请求,处理开销稍大,尤其在流量非常大的时候,可能会带来一定的性能压力。
- 适合 流量量较小或中等,但需要灵活处理的应用。
6. 灵活性
- 四层负载均衡:
- 灵活性较低,无法根据请求的具体内容做决策。
- 只能基于 IP 地址和端口进行负载均衡。
- 七层负载均衡:
- 高度灵活,能够根据请求的内容(如路径、请求方法等)做多种处理。
- 可以执行复杂的路由策略,例如 A/B 测试、基于域名分流等。
7. 举例:
- 四层负载均衡:适用于 数据库、非 HTTP 服务 的负载均衡,如 MySQL、Redis、TCP 服务等。
- 七层负载均衡:适用于 Web 应用、API 服务 的负载均衡,例如分发 HTTP 请求到不同的后端 Web 服务。
8.应用场景
特性 | 四层负载均衡 | 七层负载均衡 |
---|---|---|
应用场景 | - 数据库、内存存储(Redis、MySQL) | - Web 应用、API、动态内容分发(电商、社交网站) |
- 视频流、游戏、实时通信 | - A/B 测试、灰度发布、基于路径或子域名的路由 | |
- FTP 服务、VPN | - 用户认证、WebSocket 连接、API 网关 | |
- 需要高并发、低延迟的服务 | - 需要处理 HTTP 请求内容、SSL 终止代理 |