土法炼钢兴趣小组的算法知识备份

【网络工程】负载均衡算法深度解析:从轮询到 P2C

文章导航

分类入口
network
标签入口
#load-balancing#algorithms#consistent-hashing#p2c#scheduling

目录

负载均衡算法的选择直接影响系统的吞吐量、尾延迟和可用性。一个看似简单的”Round Robin”在后端处理时间不均匀时会导致请求堆积;一个”Least Connection”在连接数不能反映真实负载时会做出错误决策。

本文从数学原理出发,分析每种算法的假设条件和失效场景,帮助你在具体场景下做出有依据的选择。

一、Round Robin 及其变体

1.1 简单轮询(Round Robin)

最简单的算法——按顺序将请求分配给后端服务器。假设有 N 台服务器,第 i 个请求分配给第 i % N 台。

class RoundRobin:
    def __init__(self, servers):
        self.servers = servers
        self.index = 0

    def next(self):
        server = self.servers[self.index % len(self.servers)]
        self.index += 1
        return server

# 使用
rr = RoundRobin(["A", "B", "C"])
# 请求序列: A, B, C, A, B, C, A, ...

假设条件:所有服务器的处理能力相同,所有请求的处理成本相同。

失效场景: - 服务器性能不同(新旧机器混部) - 请求处理时间差异大(查询列表 vs 导出报表) - 长连接场景(一个连接占用一台服务器很久)

1.2 加权轮询(Weighted Round Robin)

给每台服务器一个权重,处理能力强的分配更多请求:

class WeightedRoundRobin:
    """Nginx 的平滑加权轮询算法"""
    def __init__(self, servers):
        # servers: [(name, weight), ...]
        self.servers = servers
        self.weights = [w for _, w in servers]
        self.current_weights = [0] * len(servers)
        self.total_weight = sum(self.weights)

    def next(self):
        # 1. 每个节点的 current_weight 加上自身 weight
        for i in range(len(self.servers)):
            self.current_weights[i] += self.weights[i]

        # 2. 选择 current_weight 最大的节点
        max_idx = self.current_weights.index(max(self.current_weights))

        # 3. 被选中节点的 current_weight 减去 total_weight
        self.current_weights[max_idx] -= self.total_weight

        return self.servers[max_idx][0]

# 权重 A:5, B:1, C:1 的调度序列
wrr = WeightedRoundRobin([("A", 5), ("B", 1), ("C", 1)])
# 序列: A, A, B, A, C, A, A  (7 个请求中 A 得到 5 个)
# Nginx 的算法保证分布均匀,不会出现 A,A,A,A,A,B,C 这种连续分配

Nginx 的平滑加权轮询(Smooth WRR)确保请求在所有服务器间平滑分布,避免某台服务器连续接收大量请求。这对缓存友好性和突发负载处理很重要。

来看一个具体的调度序列,理解 Smooth WRR 的行为。假设三台服务器权重为 A:5, B:1, C:1(总权重 7):

轮次  current_weight 累加后    选中   current_weight 减总权重后
 1    [5, 1, 1]               A      [-2, 1, 1]
 2    [3, 2, 2]               A      [-4, 2, 2]
 3    [1, 3, 3]               B      [1, -4, 3]
 4    [6, -3, 4]              A      [-1, -3, 4]
 5    [4, -2, 5]              C      [4, -2, -2]
 6    [9, -1, -1]             A      [2, -1, -1]
 7    [7, 0, 0]               A      [0, 0, 0]   ← 一个完整周期

序列: A, A, B, A, C, A, A

注意 B 和 C 均匀分散在 A 之间,而不是 A,A,A,A,A,B,C。这种平滑分布意味着任何时间窗口内的负载都相对均匀。

1.3 Round Robin 的工程问题

在 HTTP/2 和 gRPC 场景下,RR 有一个隐蔽的问题。HTTP/2 使用单连接多路复用,所有请求都在一个 TCP 连接上。如果 L4 LB 用 RR 调度 TCP 连接,某台 L7 LB 可能承担了大部分 HTTP/2 流量:

Client (HTTP/2, 单连接) → L4 LB (RR 调度连接)
  → 连接 1 → L7-A (承载 1000 RPS)
  
Client (HTTP/1.1, 多连接) → L4 LB (RR 调度连接)
  → 连接 1 → L7-A (10 RPS)
  → 连接 2 → L7-B (10 RPS)
  → 连接 3 → L7-C (10 RPS)
  ...

# L7-A 的负载远超 L7-B 和 L7-C
# 解决方案:在 L7 层用请求级 RR,不要在 L4 层用连接级 RR 调度 HTTP/2

二、Least Connection 算法

2.1 基本原理

最少连接(Least Connection,LC)选择当前活跃连接数最少的服务器。它的核心思想是:连接数少的服务器当前负载可能更低。

import heapq
from threading import Lock

class LeastConnection:
    def __init__(self, servers):
        # (active_connections, server_name)
        self.heap = [(0, s) for s in servers]
        heapq.heapify(self.heap)
        self.lock = Lock()
        self.conn_count = {s: 0 for s in servers}

    def acquire(self):
        with self.lock:
            _, server = heapq.heappop(self.heap)
            self.conn_count[server] += 1
            heapq.heappush(self.heap, (self.conn_count[server], server))
            return server

    def release(self, server):
        with self.lock:
            self.conn_count[server] -= 1
            # 重建堆(简化实现,实际用索引堆更高效)
            self.heap = [(self.conn_count[s], s) for s in self.conn_count]
            heapq.heapify(self.heap)

2.2 加权最少连接(WLC)

将权重纳入计算,选择 active_connections / weight 最小的服务器:

overhead = active_connections / weight

Server A: 10 connections, weight=5 → overhead = 2.0
Server B: 8 connections, weight=2  → overhead = 4.0
Server C: 6 connections, weight=3  → overhead = 2.0

选择 overhead 最小的: A 或 C(如果相同,选第一个)

IPVS 的 WLC 实现使用整数运算避免浮点除法:

// 内核中的比较:a.conn * b.weight < b.conn * a.weight
// 等价于:a.conn/a.weight < b.conn/b.weight
// 但避免了除法运算

2.3 LC 的局限性

连接数 ≠ 负载。LC 算法假设每个连接的负载相同,但现实中:

场景 连接数 实际负载 LC 的判断
10 个空闲 WebSocket 10 以为负载高
1 个大文件上传 1 以为负载低
5 个 SELECT 查询 5 以为负载中
1 个大 JOIN 查询 1 以为负载低

长连接场景下的惊群效应。当一台新服务器加入时,它的连接数为 0,所有新请求都会涌向它,造成瞬间过载:

现有状态:
  A: 100 connections
  B: 95 connections
  C: 0 connections  ← 刚加入

LC 的行为: 所有新请求都去 C,直到 C 的连接数追上 A 和 B
实际效果: C 在启动后几秒内被打满

解决方案:
1. 慢启动 (Slow Start): 新加入的服务器权重从 0 逐渐增加
2. 连接数上限: 设置每台服务器的最大连接数
# Nginx 慢启动配置
upstream backend {
    server 10.0.2.10:8080 slow_start=30s;  # 30 秒内权重从 0 增加到设定值
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

三、哈希算法

3.1 源 IP 哈希

将客户端 IP 哈希后映射到后端服务器,保证同一客户端始终访问同一后端:

def ip_hash(client_ip, servers):
    h = hash(client_ip) % len(servers)
    return servers[h]

问题:当服务器数量变化时,几乎所有客户端的映射都会改变——这对有状态服务(如购物车、登录 session)是灾难性的。

3.2 一致性哈希(Consistent Hashing)

一致性哈希解决了服务器增减时的映射变化问题。将服务器和键都映射到一个哈希环上:

import hashlib
import bisect

class ConsistentHash:
    def __init__(self, servers, replicas=150):
        self.ring = []            # 排序的哈希值列表
        self.hash_to_server = {}  # 哈希值 → 服务器映射
        self.replicas = replicas  # 每个服务器的虚拟节点数

        for server in servers:
            self.add_server(server)

    def _hash(self, key):
        return int(hashlib.md5(key.encode()).hexdigest(), 16)

    def add_server(self, server):
        for i in range(self.replicas):
            h = self._hash(f"{server}:{i}")
            self.ring.append(h)
            self.hash_to_server[h] = server
        self.ring.sort()

    def remove_server(self, server):
        for i in range(self.replicas):
            h = self._hash(f"{server}:{i}")
            self.ring.remove(h)
            del self.hash_to_server[h]

    def get_server(self, key):
        if not self.ring:
            return None
        h = self._hash(key)
        idx = bisect.bisect_right(self.ring, h) % len(self.ring)
        return self.hash_to_server[self.ring[idx]]

# 当移除 Server B 时:
# 只有原本映射到 B 的键会重新映射到 B 的后继节点
# 其他键的映射不变
# 理论上只有 1/N 的键需要重新映射

虚拟节点的重要性。如果每个服务器只有一个哈希值,负载分布会非常不均匀。150 个虚拟节点可以将负载差异控制在 10% 以内:

虚拟节点数 负载标准差 最大/最小比
1 85% 10x+
10 30% 3-4x
50 12% 1.5x
150 7% 1.2x
500 4% 1.1x

3.3 一致性哈希在 LB 中的应用

一致性哈希最适合需要缓存亲和性的场景——同一个键的请求总是到达同一台服务器,最大化缓存命中率:

# Nginx 一致性哈希配置
upstream cache_backend {
    hash $request_uri consistent;  # 基于 URI 的一致性哈希
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

# 缓存代理场景
upstream cdn_origin {
    hash $uri consistent;
    server cache1:8080;
    server cache2:8080;
    server cache3:8080;
}

3.4 有界负载一致性哈希

Google 在 2017 年提出了有界负载一致性哈希(Consistent Hashing with Bounded Loads),解决一致性哈希中个别节点负载过高的问题:

class BoundedLoadConsistentHash(ConsistentHash):
    """有界负载一致性哈希"""
    def __init__(self, servers, replicas=150, load_factor=1.25):
        super().__init__(servers, replicas)
        self.load_factor = load_factor
        self.load = {s: 0 for s in servers}
        self.total_load = 0

    def _max_load(self):
        """每台服务器的负载上限"""
        avg = self.total_load / len(self.load) if self.load else 0
        return max(1, int(avg * self.load_factor))

    def get_server(self, key):
        h = self._hash(key)
        idx = bisect.bisect_right(self.ring, h) % len(self.ring)
        max_load = self._max_load()

        # 沿环顺时针查找,跳过已超载的节点
        for _ in range(len(self.ring)):
            server = self.hash_to_server[self.ring[idx]]
            if self.load.get(server, 0) < max_load:
                self.load[server] = self.load.get(server, 0) + 1
                self.total_load += 1
                return server
            idx = (idx + 1) % len(self.ring)

        # fallback: 选负载最小的
        return min(self.load, key=self.load.get)

四、P2C:Power of Two Choices

4.1 超市收银台问题

假设你在超市结账,排队策略有三种:

  1. 随机选一个队:可能选到最长的队。
  2. 选最短的队:需要看所有队,信息获取成本高。
  3. 随机看两个队,选短的:只看两个队,效果接近最优。

这就是 P2C(Power of Two Random Choices)的核心思想——从全局最优退化到两个随机样本中选较好的,信息成本大幅降低,但效果几乎不变

数学上,Michael Mitzenmacher 在 2001 年的论文中证明:

策略 最大队列长度(期望)
随机选 1 个 O(log n / log log n)
随机选 2 个,取较好的 O(log log n)
选全局最优 O(log log n)

关键洞察:从 1 个选择增加到 2 个选择,带来的改善是指数级的(从 log n 到 log log n)。但从 2 增加到 3、4,改善很小。这就是为什么叫 “Power of Two Choices”。

用具体数字感受差距。假设 1000 台服务器:

随机选 1 个:  max load ≈ log(1000) / log(log(1000))
            ≈ 6.9 / 1.93 ≈ 3.6(平均负载的 3.6 倍)

随机选 2 个:  max load ≈ log(log(1000))
            ≈ log(6.9) ≈ 1.93(平均负载的 1.93 倍)

差距巨大: 3.6x → 1.93x,仅仅多看一个候选

4.2 P2C 在负载均衡中的实现

import random

class P2C:
    """Power of Two Choices 负载均衡"""
    def __init__(self, servers):
        self.servers = {s: 0 for s in servers}  # server → active requests

    def pick(self):
        servers = list(self.servers.keys())

        if len(servers) == 1:
            return servers[0]

        # 随机选两个不同的服务器
        a, b = random.sample(servers, 2)

        # 返回负载较低的
        if self.servers[a] <= self.servers[b]:
            self.servers[a] += 1
            return a
        else:
            self.servers[b] += 1
            return b

    def done(self, server):
        self.servers[server] = max(0, self.servers[server] - 1)

4.3 P2C 的工程优势

为什么 P2C 在分布式系统中越来越受欢迎?

维度 LC (全局最少连接) P2C
信息需求 所有服务器的连接数 只需 2 个服务器的信息
同步开销 全局同步(热点锁) 无需同步
适合分布式 困难(信息不一致) 天然适合
惊群效应 严重(新节点被涌入) 轻微
尾延迟 接近最优

在分布式环境中,每个 LB 节点无法实时获取所有后端的真实负载。LC 需要全局视图,但全局视图有延迟——100ms 前的”最少连接”可能现在已经不是了。P2C 只需要局部信息,对信息延迟容忍度高。

4.4 gRPC 的 P2C 实现

gRPC 的 client-side load balancing 默认使用 P2C,且加入了延迟因子:

// gRPC pick_first → round_robin → P2C (with EWMA latency)
// P2C 结合 EWMA 延迟的伪代码

type Server struct {
    Addr        string
    ActiveReqs  int64
    AvgLatency  float64  // EWMA 延迟
}

func p2cPick(servers []*Server) *Server {
    // 随机选两个
    a := servers[rand.Intn(len(servers))]
    b := servers[rand.Intn(len(servers))]
    for b == a {
        b = servers[rand.Intn(len(servers))]
    }

    // 综合考虑活跃请求数和延迟
    scoreA := float64(a.ActiveReqs+1) * a.AvgLatency
    scoreB := float64(b.ActiveReqs+1) * b.AvgLatency

    if scoreA <= scoreB {
        return a
    }
    return b
}

4.5 P2C 的边界情况处理

P2C 在工程实现中需要处理几个边界情况:

class P2CRobust:
    """工程化的 P2C 实现"""
    def __init__(self, servers):
        self.servers = {s: {"active": 0, "latency": EWMA()} for s in servers}
        self.last_picked = None

    def pick(self):
        healthy = [s for s in self.servers if self.is_healthy(s)]
        if not healthy:
            return None
        if len(healthy) == 1:
            return healthy[0]

        a, b = random.sample(healthy, 2)

        # 避免连续选同一个(减少突发负载)
        if a == self.last_picked and self.score(a) == self.score(b):
            a, b = b, a

        chosen = a if self.score(a) <= self.score(b) else b
        self.servers[chosen]["active"] += 1
        self.last_picked = chosen
        return chosen

    def score(self, server):
        s = self.servers[server]
        latency = max(s["latency"].get(), 0.001)  # 防止除零
        return (s["active"] + 1) * latency

    def is_healthy(self, server):
        # 健康检查逻辑
        return True

五、Maglev 哈希

5.1 Google 的连接亲和性方案

Maglev 是 Google 在 2016 年发表的一致性哈希算法,专为网络负载均衡设计。与传统环形一致性哈希相比,Maglev 提供更均匀的负载分布和更快的查找速度:

传统一致性哈希: 哈希环 + 虚拟节点 → O(log n) 查找
Maglev:        查找表 + 置换序列 → O(1) 查找

Maglev 的核心是一个固定大小的查找表(通常为素数大小,如 65537)。每个后端通过两个哈希函数生成一个置换序列,然后按照优先级顺序填充查找表:

class MaglevHash:
    """简化的 Maglev 一致性哈希"""
    def __init__(self, backends, table_size=65537):
        self.backends = backends
        self.table_size = table_size
        self.table = self._generate_table()

    def _generate_table(self):
        n = len(self.backends)
        # 每个后端生成偏移量和步长
        permutations = []
        for backend in self.backends:
            offset = hash(backend + "_offset") % self.table_size
            skip = hash(backend + "_skip") % (self.table_size - 1) + 1
            permutations.append((offset, skip))

        table = [-1] * self.table_size
        filled = 0
        idx = [0] * n  # 每个后端的当前尝试位置

        while filled < self.table_size:
            for i in range(n):
                offset, skip = permutations[i]
                # 找到下一个空位
                pos = (offset + idx[i] * skip) % self.table_size
                while table[pos] != -1:
                    idx[i] += 1
                    pos = (offset + idx[i] * skip) % self.table_size
                table[pos] = i
                idx[i] += 1
                filled += 1
                if filled >= self.table_size:
                    break

        return table

    def lookup(self, key):
        idx = hash(key) % self.table_size
        return self.backends[self.table[idx]]

Maglev 的优势:当一台后端故障时,只有 1/N 的连接需要重新映射(与一致性哈希相同),但查找性能是 O(1),负载分布更均匀。Envoy 将 Maglev 作为其一致性哈希的默认实现。

六、EWMA 与延迟感知

5.1 EWMA 延迟追踪

指数加权移动平均(Exponentially Weighted Moving Average,EWMA)用于平滑追踪后端响应延迟:

class EWMA:
    """指数加权移动平均"""
    def __init__(self, decay=0.95):
        self.value = 0.0
        self.decay = decay
        self.initialized = False

    def update(self, sample):
        if not self.initialized:
            self.value = sample
            self.initialized = True
        else:
            self.value = self.decay * self.value + (1 - self.decay) * sample

    def get(self):
        return self.value

class LatencyAwareLB:
    """延迟感知的 P2C 负载均衡"""
    def __init__(self, servers):
        self.servers = {}
        for s in servers:
            self.servers[s] = {
                "active": 0,
                "latency": EWMA(decay=0.9),
            }

    def pick(self):
        keys = list(self.servers.keys())
        a, b = random.sample(keys, 2)

        sa = self.servers[a]
        sb = self.servers[b]

        # score = 活跃请求数 × 平均延迟
        score_a = (sa["active"] + 1) * max(sa["latency"].get(), 0.001)
        score_b = (sb["active"] + 1) * max(sb["latency"].get(), 0.001)

        chosen = a if score_a <= score_b else b
        self.servers[chosen]["active"] += 1
        return chosen

    def done(self, server, latency_ms):
        self.servers[server]["active"] -= 1
        self.servers[server]["latency"].update(latency_ms)

5.2 延迟感知的工程价值

延迟感知算法在以下场景显著优于纯连接数算法:

七、算法选型指南

6.1 决策矩阵

场景 推荐算法 原因
无状态 + 同构后端 Round Robin 最简单,无额外开销
无状态 + 异构后端 Weighted Round Robin 按处理能力分配
长连接(WebSocket/gRPC) WLC 或 P2C 需要考虑当前负载
缓存代理 一致性哈希 缓存亲和性
会话保持 IP Hash 或 Cookie Hash 同一用户到同一后端
分布式 client-side LB P2C + EWMA 无需全局信息
延迟敏感 P2C + EWMA 自动避开慢节点
混合场景 P2C(默认推荐) 综合表现最好

6.2 各 LB 软件的算法支持

算法 IPVS Nginx HAProxy Envoy gRPC
Round Robin
Weighted RR
Least Conn
IP Hash
一致性哈希
P2C
Random
Maglev

7.3 实战:算法切换的配置示例

# Nginx — 不同场景的算法配置

# 场景 1: 无状态 API,服务器同构
upstream api_stateless {
    # 最简单的 RR
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

# 场景 2: 有状态服务,需要会话保持
upstream api_stateful {
    ip_hash;  # 基于客户端 IP 的哈希
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

# 场景 3: 缓存代理,需要键亲和
upstream cache_proxy {
    hash $request_uri consistent;
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
    server 10.0.2.12:8080;
}

# 场景 4: 长连接服务,服务器异构
upstream websocket_service {
    least_conn;
    server 10.0.2.10:8080 weight=3;  # 高配机器
    server 10.0.2.11:8080 weight=2;
    server 10.0.2.12:8080 weight=1;  # 低配机器
}
# HAProxy — 算法配置

backend api_rr
    balance roundrobin
    server s1 10.0.2.10:8080 check weight 1
    server s2 10.0.2.11:8080 check weight 1

backend api_leastconn
    balance leastconn
    server s1 10.0.2.10:8080 check weight 3
    server s2 10.0.2.11:8080 check weight 1

backend cache_consistent
    balance uri                    # URI 哈希
    hash-type consistent
    server s1 10.0.2.10:8080 check
    server s2 10.0.2.11:8080 check

backend api_random_p2c
    balance random(2)              # HAProxy 2.4+ 支持 P2C
    server s1 10.0.2.10:8080 check
    server s2 10.0.2.11:8080 check
# Envoy — P2C + EWMA (默认)
clusters:
- name: api_cluster
  lb_policy: LEAST_REQUEST        # Envoy 的 LEAST_REQUEST 本质是 P2C
  least_request_lb_config:
    choice_count: 2               # 默认 2,即 P2C
  load_assignment:
    cluster_name: api_cluster
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 10.0.2.10
              port_value: 8080
      - endpoint:
          address:
            socket_address:
              address: 10.0.2.11
              port_value: 8080

7.4 算法效果验证方法

选定算法后,必须验证实际效果:

# 1. 观察后端负载分布
# Nginx access log 统计各 upstream 的请求分布
awk '{print $NF}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 如果某台服务器的请求数远超其他,说明算法选择或权重有问题

# 2. 监控后端响应时间差异
# 通过 Nginx $upstream_response_time 记录
log_format upstream_log '$remote_addr - [$time_local] '
    '"$request" $status $upstream_addr $upstream_response_time';

# 分析各后端的 P50/P99
awk '{split($NF, a, ","); for(i in a) print $6, a[i]}' /var/log/nginx/upstream.log \
    | sort | head -20

# 3. 检查连接复用率
# 如果 TIME_WAIT 很多,说明连接没有被复用
ss -tn state time-wait | awk '{print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn

# 4. 基准测试
# 用 wrk 对比不同算法的吞吐量
wrk -t4 -c100 -d30s http://10.0.1.100/api/test
# 切换算法后重新测试,对比 RPS 和延迟分布

以下是在 4 台后端(处理时间不均匀:10ms/20ms/50ms/100ms)下,各算法的表现(10000 请求,100 并发):

算法 P50 延迟 P99 延迟 最大延迟 吞吐量 负载均衡度
Round Robin 45ms 100ms 105ms 2,200 RPS 25%/25%/25%/25%
WRR (按处理速度) 28ms 85ms 102ms 3,100 RPS 40%/25%/20%/15%
Least Conn 25ms 70ms 98ms 3,400 RPS 45%/27%/18%/10%
P2C 22ms 55ms 95ms 3,600 RPS 43%/28%/19%/10%
P2C + EWMA 20ms 48ms 90ms 3,800 RPS 48%/26%/17%/9%

关键观察:

八、总结

  1. 不存在”最好的”算法,只有”最合适的”算法。RR 足够简单,在同构无状态场景下没必要用复杂算法。过度优化反而增加系统复杂度和调试难度。

  2. P2C 是当前的”默认推荐”。它在信息成本和调度效果之间取得了最好的平衡。gRPC 和 Envoy 已经将其作为默认算法。如果你的系统还在用 RR,考虑切换到 P2C。

  3. 一致性哈希是缓存场景的唯一选择。但要注意虚拟节点数量(建议 100-200)和有界负载(避免热点键导致单节点过载)。

  4. 延迟感知(EWMA)是 P2C 的最佳搭档。纯连接数不能反映真实负载,加入延迟因子后,算法能自动感知后端的处理能力变化(GC、磁盘 IO、网络抖动)。

  5. 算法选择不如正确配置重要。权重设置错误、慢启动没开、健康检查太慢——这些配置问题比算法本身影响更大。先把基础做对,再考虑高级算法。

  6. Maglev 是大规模 L4 LB 的利器。O(1) 查找性能和均匀分布让它成为 Google、Facebook 等公司在网络负载均衡器中的首选算法。Envoy 已经内置支持。


参考文献


上一篇:L7 负载均衡:HTTP 感知路由与内容交换

下一篇:健康检查与故障转移:主动探测、被动检测与优雅处理

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-08-31 · network

【网络工程】HAProxy 工程:高级配置、ACL 与运维

系统讲解 HAProxy 的工程实践:Frontend/Backend/Listen 配置模型、ACL 规则引擎的高级用法、Runtime API 的动态管理能力、多线程模型与性能调优、SSL 终止与健康检查策略,建立 HAProxy 从配置到生产运维的完整体系。

2025-08-18 · network

【网络工程】L4 负载均衡:IPVS、LVS 与连接级调度

系统讲解 L4 负载均衡的内核实现:IPVS 的工作原理与三种转发模式(NAT/DR/TUN)、调度算法选择、LVS 高可用方案(Keepalived + VIP)、云环境中的 L4 LB(NLB/MetalLB),建立传输层负载均衡的工程能力。


By .