Skip to content

负载均衡概述

应用场景: 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;
}

常见问题

  1. 为什么需要设置这些请求头?
    确保后端服务器能正确识别原始请求的域名和客户端IP,避免安全问题和日志记录错误。
  2. X-Forwarded-For和X-Real-Ip的区别?
    • X-Forwarded-For记录IP链,适用于多层代理环境。
    • X-Real-Ip直接记录客户端IP,适用于简单代理场景。
  3. 如果配置错误会发生什么?
    • 后端服务器可能无法正确识别域名,导致返回错误的网站内容。
    • 日志中记录的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. 配置复杂度

  • 四层负载均衡:
    • 配置较为简单,通常只需要设置 listenproxy_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 终止代理

感谢阅读,欢迎交流!