## 轮询算法

### 平滑加权轮询

#### 原理

每台服务器维护一个 `当前权重`（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   |



