首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Web服务器-Nginx负载均衡

Web服务器-Nginx负载均衡

作者头像
运维小路
发布2025-04-07 09:44:33
发布2025-04-07 09:44:33
8040
举报
文章被收录于专栏:运维小路运维小路

作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

我们上一大章介绍了Kubernetes的知识,本章节我们进入中间件的讲解,这里会包含很多不同的类型组件,中间件的第一个大类我这里定义的是Web服务器。由于目前使用最广泛的Web服务器是Nginx,所以我们这里的讲解主要以Nginx服务器为主。

上2个小节,我们介绍了Nginx的核心功能反向代理。但是他的一个规则只能对应一个后端,如果后端有多个同样服务跑在多个服务器上,我们Nginx这里应该如何来配置,让他支持多个后端,并实现负载均衡功能呢?

负载均衡实现

我们这里用一台后端服务器启动2个同样的服务,采用不同的端口来代替2台服务器,然后前端使用Nginx来代理这2个服务。

代码语言:javascript
复制
server {
    listen 80;
    server_name 192.168.31.120;
    location / {
        proxy_pass http://backend_servers; 
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
upstream backend_servers {
    server 192.168.31.121:8080;
    server 192.168.31.121:9090;
}

这里我们把代理的后端地址从一个具体的地址换成了我们定义的一个名字,然后在server同级的upstream模块里面定义后端的地址,这里只定义2个,实际可多个。默认情况下他他会把请求轮流转发到后端的2个服务。

负载均衡算法

如果不做任何配置的情况下就是轮询(轮流),依次向后端配置的服务转发请求。当然除了默认的轮询还有多种算法。

1. 加权轮询 (Weighted Round Robin)

  • 说明:按权重分配请求,权重越高分配越多。
  • 适用场景:服务器性能不均(如 CPU/内存差异)。
代码语言:javascript
复制
upstream backend {
    server 192.168.1.101 weight=5;  # 50% 流量
    server 192.168.1.102 weight=3;  # 30% 流量
    server 192.168.1.103 weight=2;  # 20% 流量
}

2. 最少连接数 (Least Connections)

  • 说明:优先将请求分配给当前连接数最少的服务器。
  • 适用场景:长连接服务(如 WebSocket、数据库连接池)。
代码语言:javascript
复制
upstream backend {
    least_conn;
    server 192.168.1.101;
    server 192.168.1.102;
}

3. IP 哈希 (IP Hash)

  • 说明:基于客户端 IP 计算哈希值固定分配到某台服务器。
  • 适用场景:需要会话保持的应用(如购物车、登录状态)
代码语言:javascript
复制
upstream backend {
    ip_hash;
    server 192.168.1.101;
    server 192.168.1.102;
}

4. URI 哈希 (URI Hash) - 需第三方模块

  • 说明:根据请求 URI 分配流量,相同 URI 始终到同一服务器。
  • 适用场景:缓存优化(如 CDN 边缘节点)。
  • 配置(需编译安装 ngx_http_upstream_hash_module):
代码语言:javascript
复制
upstream backend {
    hash $request_uri consistent;  # consistent 表示一致性哈希
    server 192.168.1.101;
    server 192.168.1.102;
}

健康检查逻辑

前面我们介绍他通过多种负载均衡算法转发到后端,但是后端的服务也可能出现异常,如果后端服务异常以后,Nginx还会把流量转发过去吗?默认我们只要配置负载均衡,他就会自动给我们添加健康检查,剔除不健康的节点。

代码语言:javascript
复制
#默认值
max_fails  1
fail_timeout=10s
代码语言:javascript
复制
upstream backend {
    server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
}

正常状态

两个后端服务器 101102 均处于健康状态。Nginx 使用默认的轮询策略分发请求到这两个服务器。每个请求会交替发送到101 和 102所有请求均返回

2xx3xx 等正常状态码。失败计数器(max_fails)保持为 0

故障状态

假设 192.168.1.101 发生故障,触发条件:当请求发送到 101 时,Nginx 检测到以下情况之一:连接超时(如 TCP 握手失败)。服务器返回 5xx 错误码(如 500、502)。主动拒绝连接(如服务崩溃)。

计数器递增

每次失败(如超时或错误响应),101 的失败计数器 +1。关键规则:计数器仅在 fail_timeout=30s 时间窗口内累计。(例如:30 秒内连续失败 3 次,或 30 秒内累计失败 3 次)。

标记为不可用

如果 30秒 内累计失败达到 3次,Nginx 将 101 标记为 unavailable。标记后,Nginx 停止 向 101 发送新请求,持续 30秒(fail_timeout 的第二个作用)。

流量切换

所有请求会被转发到剩余的健康节点 102。用户可能观察到部分请求失败,但服务整体仍可用(因 102 仍正常)。

故障恢复阶段

30秒后:Nginx 尝试恢复 101自动探测:当 fail_timeout=30s 超时后,Nginx 会重新将 101 加入负载均衡池。隐式检查:Nginx 不会主动发送健康检查请求,而是在下一个客户端请求触发时尝试 101。恢复逻辑:下一个请求到达时,Nginx 会尝试将请求发送到 101。如果请求成功:101 的失败计数器 重置为 0。101 重新成为健康节点,参与后续的负载均衡。

如果请求再次失败

失败计数器 +1,重新进入故障判断流程。若在 30秒 内再次累计 3次 失败,101 会再次被标记为不可用 30秒。

以上流程是我以前的理解,但是经过我测试发现目前的版本(v1.20.1), 如果把其中一个服务关闭,则请求转发会失败,但是他会把请求重新转发到另外一个正常的节点,这样前端请求就感知不到后端异常。

代码语言:javascript
复制
==> access.log <==
192.168.31.120 - - [03/Apr/2025:22:30:02 +0800] "GET / HTTP/1.1" 200 42 "-" "curl/7.29.0" "-"
192.168.31.120 - - [03/Apr/2025:22:30:04 +0800] "GET / HTTP/1.1" 200 42 "-" "curl/7.29.0" "-"
==> error.log <==
2025/04/03 22:30:06 [error] 2809#2809: *1005 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.31.120, server: 192.168.31.120, request: "GET / HTTP/1.1", upstream: "http://192.168.31.121:9090/", host: "192.168.31.120"
==> access.log <==
192.168.31.120 - - [03/Apr/2025:22:30:06 +0800] "GET / HTTP/1.1" 200 42 "-" "curl/7.29.0" "-"
192.168.31.120 - - [03/Apr/2025:22:30:08 +0800] "GET / HTTP/1.1" 200 42 "-" "curl/7.29.0" "-"

正常请求是每2秒,然后轮流转发给后端2台服务器,但是我们看到06秒的时候失败,然后06秒还有一次成功的记录(这次请求是重新转发刚刚失败的请求),这样前面的请求就感知不到后端失败。

如果你想要浮现上面的逻辑,可以显示添加参数。

代码语言:javascript
复制
location / {
  proxy_pass http://backend_servers;
  proxy_next_upstream error timeout;  # 禁用重试
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维小路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 加权轮询 (Weighted Round Robin)
  • 3. IP 哈希 (IP Hash)
  • 4. URI 哈希 (URI Hash) - 需第三方模块
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档