## 轮询算法 ### 平滑加权轮询 #### 原理 每台服务器维护一个 `当前权重`(currentWeight),每次选择 `currentWeight` 最大的服务器,选中后将其 `currentWeight` 减去总权重,然后**所有服务器都加上自己的固定权重**。如此循环,高权重节点被选中的频率更高,但不会连续出现。 #### 实际应用 - **Nginx** 的 `upstream` 默认负载均衡算法 - **LVS**(Linux Virtual Server) - 几乎所有需要「按比例分配且平滑」的场景 #### 轮询示例 ```go type server struct { name string weight int curWeight int } func NextServer(servers []*server) *server { var totalWeight int // 1.先给所有服务器加上各自的固定权重 for i := range servers { servers[i].curWeight += servers[i].weight totalWeight += servers[i].weight } // 2.再找出 curWeight 最大的服务器 maxIdx := 0 for i := 1; i < len(servers); i++ { if servers[i].curWeight > servers[maxIdx].curWeight { maxIdx = i } } // 3.选中的服务器减去总权重 servers[maxIdx].curWeight -= totalWeight return servers[maxIdx] } ``` | 轮次 | 操作前 (currentWeight) | 选中 | 操作后 | | ---- | ---------------------- | ----- | --------------- | | 初始 | A=0, B=0, C=0 | — | — | | 1 | A=5, B=1, C=1 | **A** | A=−2, B=1, C=1 | | 2 | A=3, B=2, C=2 | **A** | A=−4, B=2, C=2 | | 3 | A=1, B=3, C=3 | **B** | A=1, B=−4, C=3 | | 4 | A=6, B=−3, C=4 | **A** | A=−1, B=−3, C=4 | | 5 | A=4, B=−2, C=5 | **C** | A=4, B=−2, C=−2 | | 6 | A=9, B=−1, C=−1 | **A** | A=2, B=−1, C=−1 | | 7 | A=7, B=0, C=0 | **A** | A=0, B=0, C=0 |