# 负载均衡

## 负载均衡

当过滤器需要获取到上游群集中的主机连接时，群集管理器使用负载平衡策略来确定选择哪个主机。负载平衡策略是可插入的，并且在配置中以每个上游集群为单位进行指定。请注意，如果没有为群集配置积极的健康检查策略，则所有上游群集成员都被视为健康。

### 支持的负载平衡策略

### 轮训

这是一个简单的策略，每个健康的上游主机按循环顺序选择。

### 权重最小请求

请求最少的负载均衡器使用O(1)算法来选择两个随机的健康主机，并选择活跃请求较少的主机。（研究表明，这种方法几乎与O(N)全扫描一样好）。如果群集中的任何主机的负载均衡权重大于1，则负载均衡器将转换为随机选择主机，然后使用该主机<权重>次数的模式。这个算法对于负载测试来说简单而充分。在需要真正的加权最小请求行为的情况下（通常如果请求持续时间可变且长度较长），不应使用它。我们可能会在将来添加一个真正的全扫描加权最小请求变体来覆盖这个用例。

### 哈希环

环/模哈希负载平衡器对上游主机执行一致的哈希。该算法基于将所有主机映射到一个圆上，使得从主机集添加或移除主机的更改仅影响1/N个请求。这种技术通常也被称为“ketama”哈希。一致的散列负载均衡器只有在使用指定要散列的值的协议路由时才有效。目前唯一实现的机制是通过HTTP路由器过滤器中的HTTP头值进行散列。最小环大小默认是在运行时指定的。最小环大小控制环中每个主机的副本数。例如，如果最小环大小为1024，并且有16个主机，则每个主机将被复制64次。环哈希负载平衡器当前不支持加权重。

### 随机

随机负载均衡器选择一个随机的健康主机。如果没有配置健康检查策略，那么随机负载均衡器通常比循环更好。随机选择可以避免在发生故障的主机之后，对集群中的主机造成不均衡。

### 原始目的地

这是一个特殊用途的负载平衡器，只能与原始目标群集一起使用。上游主机是基于下游连接元数据选择的，即，连接被打开到与连接被重定向到Envoy之前传入连接的目的地地址相同的地址。新的目的地由负载均衡器按需添加到集群，并且集群定期清除集群中未使用的主机。原始目标群集不能使用其他负载平衡类型。

### 恐慌阈值

在负载均衡期间，Envoy通常只考虑上游群​​集中的健康主机。但是，如果群体中的健康主机的百分比变得太低，Envoy就会忽略所有主机中的健康状况和平衡。这被称为恐慌阈值。默认的恐慌阈值是50％。这可以通过运行时配置。恐慌阈值用于避免因主机故障，造成整个集群负荷加重的情况。

### 优先级

在负载均衡期间，Envoy通常只考虑配置在最高优先级的主机。对于每个EDS LocalityLbEndpoints，还可以指定一个可选的优先级。目前，使得从一个优先级到另一个优先级的路由故障转移机制，变得相当简单：根据给定的优先级，直到它具有零个健康的主机，在这一点上，切换到下一个最高优先级很难失败。

### 区域感知路由

我们会使用以下术语：

* **始发/上游集群**：Envoy将来自原始集群的请求路由到上游集群。
* **本地区域**：包含始发和上游群集中的主机，同属一个区域。
* **区域感知路由**：尽力将请求路由到本地区域中的上游群集主机。\ <br>

在原始和上游群集中的主机属于不同区域的部署中，Envoy执行区域感知路由。在区域感知路由执行之前，有几个先决条件：

* 发起和上游集群都不处于恐慌状态。
* 区域感知路由已启用。
* 源群集与上游群集具有相同的区域数量。
* 上游集群有足够的主机。 浏览[此处](/envoy/introduction/architectureoverview/runtimeconfiguration.md)获取更多信息。\ <br>

区域感知路由的目的是尽可能多地向本地区域所在的上游群集发送流量，同时在所有上游主机（取决于负载平衡策略），每个主机每秒大致保持相同数量的请求。

只要维持上游集群中每台主机的请求数量大致相同，Envoy就会尝试尽可能多地将流量推送到本地上游区域。决定Envoy路由到本地区域还是执行跨区域路由，取决于本地区域中始发群集和上游群集中健康主机的百分比。在原始和上游集群之间的本地区的百分比关系有两种情况：

* 源集群本地区域百分比大于上游群集中的百分比。在这种情况下，我们不能将来自原始集群的本地区域的所有请求路由到上游集群的本地区域，因为这将导致所有上游主机的请求不平衡。相反，Envoy会计算可以直接路由到上游群集的本地区域的请求的百分比。其余的请求被路由到跨区域。特定区域是根据区域的剩余容量（该区域将获得一些本地区域业务量并且可能具有Envoy可用于跨区域业务量的额外容量）来选择。
* 发起群集本地区域百分比小于上游群集中的百分比。在这种情况下，上游集群的本地区域可以获得来自原始集群本地区域的所有请求，并且还有一定的空间允许来自发起集群中其他区域的流量（如果需要）。

### 负载平衡器子集

Envoy可能被配置为根据附加到主机的元数据，将上游集群中的主机划分为多个子集。然后可以指定主机必须匹配的元数据，提供给负载平衡器进行路由，并且也可以选择回退到预定义的一组主机（包括任何主机）。

子集使用集群指定的负载平衡器策略。原来的目标策略可能不能与子集一起使用，因为上游主机事先不知道。子集与区域感知路由兼容，但请注意，使用子集可能很容易违反上述的最小主机条件。

如果子集已配置且路由未指定元数据或没有与元数据匹配的子集，则子集负载均衡器将启动其后备策略。默认策略是NO\_ENDPOINT，在这种情况下，请求失败，就好像群集没有主机一样。相反，ANY\_ENDPOINT后备策略会在群集中的所有主机之间进行负载均衡，而不考虑主机元数据。最后，DEFAULT\_SUBSET会导致回退至与Envoy元数据集匹配的主机之间进行负载均衡。

子集必须预定义为允许子集负载均衡器有效地选择正确的主机子集。每个定义都是一组Key，可以转换为零个或多个子集。从概念上讲，每个具有定义中所有Key的元数据值的主机都将被添加到特定于其Key值对的子集中。如果没有主机拥有所有的密钥，那么定义就不会产生子集。可以提供多个定义，并且如果单个主机匹配多个定义，则其可以出现在多个子集中。

在路由期间，路由的元数据匹配这些配置（用于查找特定的子集）。如果存在具有由路由指定的确切Key和Value的子集，则该子集用于负载平衡。否则，使用回退策略。因此，集群的子集配置必须包含与给定路由具有相同Key的定义，以便使能子集负载平衡。

此功能只能使用V2 API启用配置。此外，主机元数据仅支持在群集使用EDS发现类型时使用。子集负载平衡的主机元数据必须放在过滤器名称“envoy.lb”下。同样，路由元数据匹配条件使用“envoy.lb”过滤器名称。主机元数据可以是分层的（例如，顶级key的值可以是结构化值或列表），但子集负载平衡器仅比较顶级key和value。因此，当使用结构化值时，如果主机的元数据中出现相同的结构化值，那么路由只会匹配相同的结构化值。

### 示例

我们将使用所有值都是字符串的简单元数据。假定定义了以下主机并将其与集群关联：

| 主机    |           元数据          |
| ----- | :--------------------: |
| host1 |   v: 1.0, stage: prod  |
| host2 |   v: 1.0, stage: prod  |
| host3 |  v: 1.1, stage: canary |
| host4 | v: 1.2-pre, stage: dev |

\
&#x20;集群启用子集负载平衡，如下所示：

```
---
name: cluster-name
type: EDS
eds_cluster_config:
  eds_config:
    path: '.../eds.conf'
connect_timeout:
  seconds: 10
lb_policy: LEAST_REQUEST
lb_subset_config:
  fallback_policy: DEFAULT_SUBSET
  default_subset:
    stage: prod
  subset_selectors:
  - keys:
    - v
    - stage
  - keys:
    - stage
```

下表介绍了一些路由及其在集群中的应用结果。通常，根据请求特征与路由匹配一起使用，例如路径或报文头信息。

| 匹配准则                   |      落点      | 原因              |
| ---------------------- | :----------: | --------------- |
| stage: canary          |     host3    | 主机的子集匹配         |
| v: 1.2-pre, stage: dev |     host4    | 主机的子集匹配         |
| v: 1.0                 | host1, host2 | 回退：没有单独的“v”的子集  |
| other: x               | host1, host2 | 回退：没有“other”的子集 |
| (none)                 | host1, host2 | 回退：没有要求的子集      |

\
&#x20;元数据匹配标准也可以在路由的加权群集上指定。来自所选加权群集的元数据匹配条件将与路线中的条件合并并覆盖该条件：

| 路由匹配准则              | 加权集群匹配准则              | 最终匹配准则                |
| ------------------- | --------------------- | --------------------- |
| stage: canary       | stage: prod           | stage: prod           |
| v: 1.0              | stage: prod           | v: 1.0, stage: prod   |
| v: 1.0, stage: prod | stage: canary         | v: 1.0, stage: canary |
| v: 1.0, stage: prod | v: 1.1, stage: canary | v: 1.1, stage: canary |
| (none)              | v: 1.0                | v: 1.0                |
| v: 1.0              | (none)                | v: 1.0                |

### 具有元数据主机的示例

具有主机元数据的EDS LbEndpoint：

```
---
endpoint:
  address:
    socket_address:
      protocol: TCP
      address: 127.0.0.1
      port_value: 8888
metadata:
  filter_metadata:
    envoy.lb:
      version: '1.0'
      stage: 'prod'
```

### 具有元数据路由的示例

具有元数据匹配的RDS路由标准：

```
---
match:
  prefix: /
route:
  cluster: cluster-name
  metadata_match:
    filter_metadata:
      envoy.lb:
        version: '1.0'
        stage: 'prod'
```

## 返回

* [架构介绍](/envoy/introduction/architectureoverview.md)
* [简介](/envoy/introduction.md)
* [首页目录](/envoy/master.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lixiangyun.gitbook.io/envoy/introduction/architectureoverview/loadbalancing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
