外观
按权重分发的负载均衡算法怎么实现
⭐ 题目日期:
字节 - 2025/7/16
📝 题解:
要实现按权重分发的负载均衡算法,核心是根据服务器权重分配请求流量,权重高的服务器获得更多请求。以下是两种常见实现方式及代码示例:
1. 随机权重算法(无状态)
原理:根据权重生成虚拟区间,随机数落入哪个区间则选择对应服务器。
特点:无状态、简单高效,适合短连接场景。
import random
class WeightedRandomLB:
def __init__(self, servers):
"""
servers: 服务器列表,格式 [("server1", weight1), ("server2", weight2), ...]
"""
self.servers = servers
self.total_weight = sum(weight for _, weight in servers)
# 构建权重累积区间 [0, w1), [w1, w1+w2), ...
self.accumulated = []
accum = 0
for _, weight in servers:
accum += weight
self.accumulated.append(accum)
def get_server(self):
rand_val = random.uniform(0, self.total_weight)
for idx, acc in enumerate(self.accumulated):
if rand_val <= acc:
return self.servers[idx][0]
使用示例:
servers = [("A", 3), ("B", 1), ("C", 2)] # 总权重6
lb = WeightedRandomLB(servers)
print(lb.get_server()) # 输出:约50%概率返回A,16.7%概率B,33.3%概率C
2. 平滑加权轮询算法(有状态)
原理:动态调整当前权重,避免低权重服务器长时间饥饿。
特点:请求分布更平滑,适合长连接场景。
class SmoothWeightedRoundRobin:
def __init__(self, servers):
self.servers = servers
self.current_weights = {} # 当前权重动态值
self.effective_weights = {} # 有效权重(初始=固定权重)
for server, weight in servers:
self.current_weights[server] = 0
self.effective_weights[server] = weight
self.total_weight = sum(weight for _, weight in servers)
def get_server(self):
# 1. 当前权重 += 有效权重
for server, _ in self.servers:
self.current_weights[server] += self.effective_weights[server]
# 2. 选出当前权重最大的服务器
best_server = max(self.current_weights, key=self.current_weights.get)
# 3. 被选中的服务器减去总权重
self.current_weights[best_server] -= self.total_weight
return best_server
使用示例:
servers = [("A", 3), ("B", 1), ("C", 2)] # 总权重6
lb = SmoothWeightedRoundRobin(servers)
# 连续调用6次,输出序列如:A, A, C, A, C, B
for _ in range(6):
print(lb.get_server())
关键点说明
权重分配:
- 随机算法:每次独立选择,概率=权重/总权重。
- 平滑轮询:每轮请求分布严格按权重比例(如上例中3:1:2)。
动态权重调整:
- 平滑轮询算法通过
当前权重 -= 总权重
避免权重累积溢出。 - 可扩展:若服务器故障,可将其有效权重设为0临时剔除。
- 平滑轮询算法通过
适用场景:
- 随机权重:适用于无状态短请求(如HTTP API)。
- 平滑轮询:适用于需要均匀分配的场景(如TCP长连接)。
进阶优化:
- 增加健康检查机制,自动跳过故障节点。
- 结合响应时间动态调整权重(自适应负载均衡)。
两种算法均能实现权重分发,选择取决于具体场景。平滑轮询算法虽稍复杂,但能避免低权重服务器“饥饿”,是生产环境推荐方案。