# xds

xDS REST和gRPC协议 Envoy通过文件系统或查询一台或多台管理服务器发现其各种动态资源。这些发现服务及其相应的API统称为xDS。通过预订,指定要监视的文件系统路径,启动gRPC流或轮询REST-JSON URL来请求资源。后两种方法涉及发送带有DiscoveryRequest 原型有效负载的请求.在所有方法中,资源都是通过DiscoveryResponse原型有效负载交付的 。我们在下面讨论每种订阅类型。

## 资源类型

xDS API中的每个配置资源都有与之关联的类型。资源类型遵循 版本控制方案。资源类型的版本与下面描述的传输无关。

支持以下v3 xdS资源类型:

* envoy.config.listener.v3.Listener
* envoy.config.route.v3.RouteConfiguration
* envoy.config.route.v3.ScopedRouteConfiguration
* envoy.config.route.v3.VirtualHost
* envoy.config.cluster.v3.Cluster
* envoy.config.endpoint.v3.ClusterLoadAssignment
* envoy.extensions.transport\_sockets.tls.v3.Secret
* envoy.service.runtime.v3.Runtime

类型URL的概念 显示在下面,格式为`type.googleapis.com/<资源类型>` – 例如, 用于集群资源的`type.googleapis.com/envoy.api.v2.Cluster`。在来自Envoy的各种请求和管理服务器的响应中,都声明了资源类型URL。

## 文件系统订阅

提供动态配置的最简单方法是将其放置在ConfigSource中指定的众所周知的路径中。Envoy将使用inotify(在macOS上为kqueue)来监视文件的更改,并在更新时解析文件中的 DiscoveryResponse原型。二进制protobufs,JSON,YAML和原型文本是DiscoveryResponse的受支持格式 。

除了统计计数器和日志外,没有文件系统订阅ACK/NACK更新的机制。如果拒绝配置更新,则xDS API的最后一个有效配置将继续适用。

## 流式gRPC订阅

### API流程

对于典型的HTTP路由方案,客户端配置的核心资源类型为 Listener,RouteConfiguration,Cluster和ClusterLoadAssignment。每个监听器资源都可以指向RouteConfiguration资源,该资源可以指向一个或多个集群资源,并且每个集群资源都可以指向ClusterLoadAssignment资源。

Envoy在启动时获取所有监听器和集群资源。然后,它获取监听器和 集群资源所需的任何 RouteConfiguration和ClusterLoadAssignment资源。实际上,每个监听器或集群资源都是Envoy配置树一部分的根。

非代理客户端,如GRPC可以通过只读取特定的启动监听器,它有兴趣的资源,然后取了RouteConfiguration那些需要的资源 监听器资源,然后取其集群是由那些需要的资源 RouteConfiguration资源,其次是ClusterLoadAssignment要求的资源集群的资源。实际上,原始监听器资源是客户端配置树的根。

### xDS传输协议的变体

### 四个变种

通过流gRPC使用的xDS传输协议有四种变体,它们涵盖了二维的所有组合。

第一个维度是世界状况(SotW)与增量。SotW方法是xDS使用的原始机制,其中客户端必须为每个请求指定其感兴趣的所有资源名称(在LDS/CDS中发出通配符请求时除外),并且服务器必须返回客户端拥有的所有资源在每个请求中订阅(在LDS/CDS中)。这意味着,如果客户端已经预订了99个资源,并且想要添加其他资源,则它必须发送包含所有100个资源名称的请求,而不仅仅是一个新的资源名称。然后,服务器必须通过发送所有100个资源来做出响应,即使已预订的99个资源没有更改(在LDS/CDS中)。此机制可能是可伸缩性限制,这就是引入增量协议变体的原因。增量方法允许客户端和服务器仅指示相对于其先前状态的增量-即,客户端可以说它想添加或删除其对特定资源名称的订阅,而不必重新发送未更改的订阅,服务器只能发送已更改资源的更新。增量协议还提供了一种资源延迟加载的机制。有关增量协议的详细信息,请参见下面的增量xDS。

第二个方面是针对每种资源类型使用单独的gRPC流,而不是将所有资源类型聚合到单个gRPC流中。前一种方法是xDS使用的原始机制,它提供了最终的一致性模型。为需要显式控制序列的环境添加了后一种方法。有关详细信息,请参阅下面的最终一致性注意事项。

因此,xDS传输协议的四个变体是:

* State of the World(Basic xDS):SotW,每种资源类型的单独gRPC流
* 增量xDS:每种资源类型的增量独立gRPC流
* 聚合发现服务(ADS):SotW,所有资源类型的聚合流
* 增量ADS:所有资源类型的增量聚合流

### 每种变体的RPC服务和方法

对于非聚合协议变体,每种资源类型都有单独的RPC服务。每个RPC服务都可以为SotW和Incremental协议变体中的每个提供一种方法。以下是每种资源类型的RPC服务和方法:

* 监听器:监听器发现服务(LDS)-SotW:监听器DiscoveryService.StreamListeners-增量:监听器DiscoveryService.DeltaListeners
* RouteConfiguration:路由发现服务(RDS)-SotW:RouteDiscoveryService.StreamRoutes-增量:RouteDiscoveryService.DeltaRoutes
* ScopedRouteConfiguration:范围路由发现服务(SRDS)-SotW:ScopedRouteDiscoveryService.StreamScopedRoutes-增量:ScopedRouteDiscoveryService.DeltaScopedRoutes
* VirtualHost:虚拟主机发现服务(VHDS)-SoW:N/A-增量:VirtualHostDiscoveryService.DeltaVirtualHosts
* cluster:集群发现服务(CDS)-前端:ClusterDiscoveryService.StreamClusters-增量:ClusterDiscoveryService.DeltaClusters
* ClusterLoadAssignment:端点发现服务(EDS)-SotW:EndpointDiscoveryService.StreamEndpoints-增量:EndpointDiscoveryService.DeltaEndpoints
* secret:机密发现服务(SDS)-机密:SecretDiscoveryService.StreamSecrets-增量:SecretDiscoveryService.DeltaSecrets
* runtime:运行时发现服务(RTDS)-SoW:RuntimeDiscoveryService.StreamRuntime-增量:RuntimeDiscoveryService.DeltaRuntime

在聚合协议变体中,所有资源类型都在单个gRPC流上多路复用,其中每种资源类型都被视为聚合流中的单独逻辑流。实际上,它通过将每种资源类型的请求和响应视为单个聚合流上的单独子流,从而将上述所有单独的API简单地组合到单个流中。聚合协议变体的RPC服务和方法是:

* SotW:AggregatedDiscoveryService.StreamAggregatedResources
* 增量式:AggregatedDiscoveryService.DeltaAggregatedResources

对于所有SotW方法,请求类型为DiscoveryRequest,响应类型为DiscoveryResponse。

对于所有增量方法,请求类型为DeltaDiscoveryRequest,响应类型为DeltaDiscoveryResponse。

### 配置要使用的变体

在xDS API中,ConfigSource消息指示如何获取特定类型的资源。如果ConfigSource 包含gRPC ApiConfigSource,则它指向管理服务器的上游集群；否则,它指向管理服务器的上游集群。这将为每种xDS资源类型(可能到不同的管理服务器)启动一个独立的双向gRPC流。如果 ConfigSource包含AggregatedConfigSource,它将告诉客户端使用ADS。

当前,期望为客户端提供一些本地配置,以告诉其如何获取监听器和集群资源.监听器资源可以包括 ConfigSource指示如何 RouteConfiguration获得资源,并且 集群资源可以包括 ConfigSource指示如何 ClusterLoadAssignment获得资源。

#### 客户端配置

在Envoy中,引导文件包含两个ConfigSource 消息,一个指示如何获取监听器资源,另一个指示如何获取集群资源。它还包含一个单独的ApiConfigSource消息,该消息指示如何联系ADS服务器,只要ConfigSource消息(在引导文件中或从管理服务器获取的监听器或集群资源中)包含AggregatedConfigSource消息,就会使用该消息。

在使用xDS的gRPC客户端中,仅支持ADS,并且引导文件包含ADS服务器的名称,该名称将用于所有资源。监听器和 集群资源中的ConfigSource消息必须包含AggregatedConfigSource消息。

### xDS传输协议

#### 传输API版本

除上述资源类型版本外,xDS有线协议还具有与之关联的传输版本。这为诸如DiscoveryRequest和DiscoveryResponse之类的消息提供了类型版本控制 。它也被编码在gRPC方法名称中,因此服务器可以根据其调用的方法来确定客户端使用的版本。

#### 基本协议概述

每个xDS流都以来自客户端的DiscoveryRequest开始,该请求指定要订阅的资源列表,与所订阅的资源相对应的类型URL,节点标识符以及指示资源类型的最新版本的可选资源类型实例版本。客户端已经看到的信息(有关详细信息,请参见 ACK/NACK和资源类型实例版本)。

然后,服务器将发送一个DiscoveryResponse,其中包含客户端已订阅的,自客户端指示看到的上一个资源类型实例版本以来已更改的任何资源。当订阅的资源发生更改时,服务器可以随时发送其他响应。

每当客户端收到新的响应时,它将发送另一个请求,指示响应中的资源是否有效(有关详细信息,请参见 ACK/NACK和资源类型实例版本)。

确保仅在流上的第一个请求中携带节点标识符。同一流上的后续发现请求可以携带一个空节点标识符。无论在同一流上接受发现响应如何,这都是正确的。如果流中不止一次出现,则节点标识符应始终相同。因此仅检查第一条消息中的节点标识符就足够了。

#### ACK/NACK和资源类型实例版本

每个xDS资源类型都有一个版本字符串,该字符串指示该资源类型的版本。只要该类型的一种资源发生更改,版本就会更改。

在xDS服务器发送的响应中, version\_info字段指示该资源类型的当前版本。然后,客户端使用version\_info字段向服务器发送另一个请求,该请求 指示客户端看到的最新有效版本。这为服务器提供了一种确定何时发送客户端认为无效的版本的方法。

(在增量协议变体中,资源类型实例版本由服务器在 system\_version\_info字段中发送。但是,客户端实际上并不使用此信息来传达哪些资源有效,因为增量API变体具有用于那。)

资源类型实例版本对于每种资源类型都是独立的。使用聚合协议变体时,即使所有资源类型都在同一流上发送,每种资源类型都有其自己的版本。

每个xDS服务器的资源类型也不同(其中xDS服务器由唯一的ConfigSource标识)。从多个xDS服务器获取给定类型的资源时,每个xDS服务器将具有不同的版本概念。

请注意,资源类型的版本不是单个xDS流的属性,而是资源本身的属性。如果流中断,并且客户端创建了新的流,则客户端对新流的初始请求应指示客户端在先前流上看到的最新版本。服务器可以决定不重新发送客户端在上一个流中已经看到的资源来进行优化,但是前提是它们知道客户端没有在订阅一个先前未预订的新资源。例如,对于服务器来说,对通配符LDS和CDS请求执行此优化通常是安全的,并且在客户端将始终订阅完全相同的资源集的环境中这样做是安全的。

一个示例EDS请求可能是:

```
version_info:
node: { id: envoy }
resource_names:
- foo
- bar
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment
response_nonce:
```

管理服务器可以立即响应,也可以在请求的资源可用DiscoveryResponse时响应,例如:

```
version_info: X
resources:
- foo ClusterLoadAssignment proto encoding
- bar ClusterLoadAssignment proto encoding
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment
nonce: A
```

在处理完DiscoveryResponse之后,Envoy将在流上发送一个新请求,指定成功应用的最后一个版本以及管理服务器提供的随机数。该版本为Envoy和管理服务器提供了当前应用的配置的共享概念,以及ACK/NACK配置更新的机制。

### ACK

如果成功应用了更新, 则按序列图所示,version\_info将为X:

![ACK后版本更新](https://www.envoyproxy.io/docs/envoy/latest/_images/simple-ack.svg)

### NACK

如果Envoy拒绝了配置更新X,它将以error\_detail 填充并且返回其先前版本(在本例中为空的初始版本)进行答复。该ERROR\_DETAIL大约有填充的消息字段确切的错误消息的详细信息:

![NACK之后没有版本更新](https://www.envoyproxy.io/docs/envoy/latest/_images/simple-nack.svg)

在顺序图中,以下格式用于缩写消息:

* DiscoveryRequest:(V =版本信息,R =资源名称,N =响应时间,T =类型网址)
* DiscoveryResponse:(V = version\_info,R =资源,N = nonce,T = type\_url)

NACK之后,API更新可能会以新版本Y成功:

![NACK之后的ACK](https://www.envoyproxy.io/docs/envoy/latest/_images/later-ack.svg)

### ACK和NACK语义摘要

* xDS客户端应从 管理服务器收到的每个DiscoveryResponse都进行ACK或NACK 。
* 像所有其他请求一样,来自DiscoveryResponse的随机数 作为response\_nonce发送。如资源更新中所述,在某些竞争条件下使用随机数来消除ACK和NACK之间的歧义。
* ACK表示成功的配置更新,包含 VERSION\_INFO从 DiscoveryResponse。
* NACK表示配置更新失败,并且包含先前(现有)的 version\_info。
* 只有NACK应该填充error\_detail。

#### 何时发送更新

仅当DiscoveryResponse中的资源已更改时,管理服务器才应将更新发送到Envoy客户端。Envoy在接受或拒绝后立即使用包含ACK/NACK的DiscoveryRequest答复任何DiscoveryResponse。如果管理服务器提供相同的资源集而不是等待更改发生,则将导致客户端和管理服务器上不必要的工作,这可能会严重影响性能。

在流中,新的DiscoveryRequests会取代所有具有相同资源类型的先前 DiscoveryRequests。这意味着管理服务器只需要对任何给定资源类型的每个流响应最新的 DiscoveryRequest。

#### 客户如何指定要返回的资源

xDS请求允许客户端指定一组资源名称,作为服务器对客户端感兴趣的资源的提示。在SotW协议变体中,这是通过DiscoveryRequest中指定的resource\_names完成 的 ；在增量协议变体中,这是通过DeltaDiscoveryRequest中的resource\_names\_subscribe和 resource\_names\_unsubscribe字段完成的 。

正常情况下(例外情况,请参见下文),请求必须指定客户端感兴趣的一组资源名称。管理服务器必须提供所请求的资源(如果存在)。客户端将无提示地忽略未明确请求的任何提供的资源。当客户端发送一个新请求来更改请求的资源集时,服务器必须重新发送任何新请求的资源,即使它先前发送的那些资源没有被要求,并且自那时以来资源也没有改变。如果资源名称列表为空,则意味着客户端不再对指定类型的任何资源感兴趣。

对于监听器和集群资源类型,还有一个"通配符"模式,当该资源类型的流上的初始请求不包含资源名称时,将触发该模式。在这种情况下,服务器通常应根据客户端的节点标识,使用特定于站点的业务逻辑来确定客户端感兴趣的全套资源。请注意,对于给定的资源类型,流已进入通配符模式,则无法将其更改为通配符模式。流上任何后续请求中指定的资源名称将被忽略。

#### 客户行为

Envoy将始终对监听器和 集群资源使用通配符模式。但是,其他xDS客户端(例如使用xDS的gRPC客户端)可以为这些资源类型指定显式资源名称,例如,如果它们仅具有单例监听器并且已经从某些带外配置中知道其名称。

#### 将资源分组为响应

在增量协议变体中,服务器以自己的响应发送每个资源。这意味着如果服务器先前已发送了100个资源,而其中只有一个已更改,则它可能会发送仅包含已更改资源的响应；它不需要重新发送99个未更改的资源,并且客户端不得删除未更改的资源。

在SotW协议变体中,除了监听器和集群以外的所有资源类型都以与增量协议变体中相同的方式分组为响应。但是, 监听器和集群资源类型的处理方式不同:服务器必须包含完整的状态,这意味着必须包含客户端所需的所有相关类型的资源,即使它们自上次响应以来没有发生变化也是如此.。这意味着,如果服务器先前已发送了100个资源,而其中只有一个已更改,则它必须重新发送所有100个资源,甚至包括99个未修改的资源。

请注意,所有协议变体都以整个命名资源为单位进行操作。没有机制可以提供命名资源中重复字段的增量更新。最值得注意的是,当前没有机制可以在EDS响应中增量更新各个端点。

#### 资源名称重复

服务器发送包含两次相同资源名称的单个响应是错误的。客户端应在NACK响应中包含相同资源名称的多个实例。

#### 删除资源

在增量协议版本中,服务器通过 响应的removed\_resources字段通知客户端应删除资源。这告诉客户端从其本地缓存中删除资源。

在SotW协议变体中,删除资源的标准更加复杂。对于 监听器和集群资源类型,如果新响应中不存在以前看到的资源,则表明该资源已被删除,客户端必须删除它；否则,客户端必须删除它。不包含资源的响应意味着删除该类型的所有资源。但是,对于其他资源类型,API没有为服务器提供任何机制来告知客户端资源已删除。而是通过将父资源更改为不再引用子资源来隐式指示删除。例如,当客户端收到LDS更新时,如果没有其他 指示,则删除以前指向RouteConfiguration A的监听器监听器指向RouteConfiguration A,然后客户端可以删除A。对于那些资源类型,从客户端的角度来看,空的DiscoveryResponse实际上是无操作的。

#### 知道何时不存在所请求的资源

SotW协议变体不提供任何明确的机制来确定何时不存在所请求的资源。

监听器和集群 资源类型的响应必须包括客户端请求的所有资源。但是,客户端可能无法仅基于响应中不存在资源就知道不存在资源,因为更新的传递最终是一致的:如果客户端最初发送对资源A的请求,则发送对资源A和B的请求,然后看到仅包含资源A的响应,客户端无法断定资源B不存在,因为在服务器看到第二个请求之前,响应可能是根据第一个请求发送的请求。

对于其他资源类型,因为每个资源都可以在其自己的响应中发送,所以无法从下一个响应中知道新请求的资源是否存在,因为下一个响应可能是与已订阅的另一个资源无关的更新到以前。

结果,客户端应在发送新资源请求后使用超时(建议的持续时间为15秒),此后,如果未收到资源,则客户端将认为请求的资源不存在。在Envoy中,这是在资源预热期间对RouteConfiguration和ClusterLoadAssignment资源完成的 。

请注意,对于监听器和集群资源类型使用通配符模式时,此超时并非绝对必要,因为在这种情况下,每个响应都将包含与客户端相关的所有现有资源,因此客户端可以知道该客户端不存在该资源。在下一个响应中看到缺席。但是,在这种情况下,仍建议使用超时,因为这样可以防止管理服务器无法及时发送响应的情况。

请注意,即使客户端请求时所请求的资源不存在,也可以随时创建该资源。管理服务器必须记住客户端正在请求的资源集,并且如果其中一个资源后来出现,服务器必须将更新发送给客户端,以通知其新资源。最初看到不存在的资源的客户端必须准备随时创建该资源。

#### 退订资源

在增量协议变体中,可以通过resource\_names\_unsubscribe字段取消订阅 资源。

在SotW协议变体中,每个请求必须在resource\_names字段中包含要预订的资源名称的完整列表,因此,通过发送包含所有仍在预订但未预订的所有资源名称的新请求来取消预订一组资源包含要取消订阅的资源名称。例如,如果客户端先前已订阅资源A和B,但希望取消订阅B,则它必须发送仅包含资源A的新请求。

请注意,对于 流处于"通配符"模式的监听器和集群资源类型(有关详细信息,请参见客户端如何指定要返回的资源),要订阅的资源集由服务器而不是由客户端确定,因此客户端无法退订资源的机制。

#### 在单个流上请求多个资源

对于EDS/RDS,Envoy可以为给定类型的每个资源生成不同的流(例如,如果每个ConfigSource具有其自己的不同的上游管理服务器集群),或者可以在给定资源类型时将多个资源请求组合在一起预定用于同一管理服务器。虽然这留给实现细节,但管理服务器应该能够处理每个请求中给定资源类型的一个或多个resource\_name。以下两个序列图均适用于获取两个EDS资源{foo,bar}:

![同一流上有多个EDS请求 不同流上的多个EDS请求](https://www.envoyproxy.io/docs/envoy/latest/_images/eds-distinct-stream.svg)

#### 资源更新

如上所讨论的,envoy可更新列表resource\_names其呈现给在每个管理服务器DiscoveryRequest该ACK/NACK的一特定DiscoveryResponse。此外,Envoy稍后可能会在给定的version\_info上发出其他DiscoveryRequest,以使用新的资源提示来更新管理服务器。例如,如果Envoy的版本为EDS X,并且仅了解集群,但随后又收到CDS更新并了解其他信息,则它可能会向X发出附加的DiscoveryRequest,其中{foo,bar}为 resource\_names。foobar

![CDS响应导致EDS资源提示更新](https://www.envoyproxy.io/docs/envoy/latest/_images/cds-eds-resources.svg)

这里可能会出现比赛条件；如果Envoy在X发布资源提示更新之后,但是在管理服务器处理更新之前,它用新版本Y答复,则可以通过提供 X version\_info将资源提示更新解释为Y拒绝。为了避免这种情况,管理服务器提供一个 Envoy用来指示 每个DiscoveryRequest对应的特定DiscoveryResponse: nonce

![EDS更新竞赛激发了随机数](https://www.envoyproxy.io/docs/envoy/latest/_images/update-race.svg)

管理服务器不应为任何 具有过期随机数的DiscoveryRequest发送DiscoveryResponse。在DiscoveryDissponse中向Envoy提出新的现时之后,现时变得陈旧 。在确定有新版本可用之前,管理服务器无需发送更新。这样一来,早期版本的请求也会过时。它可能会在一个版本中处理多个 DiscoveryRequest,直到准备好新版本为止。

![请求过时](https://www.envoyproxy.io/docs/envoy/latest/_images/stale-requests.svg)

上述资源更新测序的一个意义是envoy估计不会有DiscoveryResponse为每DiscoveryRequests 它的问题。

## 资源升温

集群和 监听器 需要经过预热才能提供服务。此过程在Envoy初始化期间 以及集群或监听器更新时都会发生。仅当管理服务器提供ClusterLoadAssignment响应时, 集群预热才完成。同样,仅当RouteConfiguration时才完成监听器的预热如果监听器引用RDS配置,则由管理服务器提供。预计管理服务器将在预热期间提供EDS/RDS更新。如果管理服务器不提供EDS/RDS响应,则Envoy不会在初始化阶段自行初始化,并且在提供EDS/RDS响应之前,通过CDS/LDS发送的更新将不会生效。

## 最终一致性考虑

由于Envoy的xDS API最终是一致的,因此更新期间流量可能会短暂下降。例如,如果只簇X通过CDS知/ EDS,一个RouteConfiguration集群引用X,然后被调节到集群Ÿ只是CDS/EDS更新提供前 Ÿ,交通会遭到忽略,直到Ÿ有人知道由envoy实例。

对于某些应用程序,暂时的流量下降是可以接受的,在客户端或由其他Envoy边车重试将隐藏该流量下降。对于不能容忍丢弃的其他情况,可以通过同时提供X和 Y的CDS/EDS更新,然后将RDS更新从X指向Y以及随后的CDS/EDS更新丢弃X来避免流量下降。

通常,为了避免流量下降,更新顺序应遵循先停后通模型,其中:

必须始终首先推送CDS更新(如果有)。

EDS更新(如果有)必须在相应集群的CDS更新之后到达。

LDS更新必须在相应的CDS/EDS更新之后到达。

与新添加的监听器相关的RDS更新必须在CDS/EDS/LDS更新之后到达。

与新添加的RouteConfiguration相关的VHDS更新(如果有)必须在RDS更新之后到达。

然后,可以删除陈旧的CDS集群和相关的EDS端点(不再被引用的端点)。

如果未添加新的集群/路由/监听器,或者在更新过程中暂时丢弃流量,则可以独立推送xDS更新。请注意,在进行LDS更新的情况下,监听器将在接收流量之前被预热,即,如果已配置,则通过RDS提取相关路由。添加/删除/更新集群时,集群会预热。另一方面,不会对路由进行预热,即,管理平面必须在推送路由更新之前,确保路由引用的集群已就位。

## TTL

如果管理服务器无法访问,则Envoy收到的最新已知配置将保留,直到重新建立连接为止。对于某些服务,这可能不是理想的。例如,在故障注入服务的情况下,管理服务器在错误的时间崩溃可能会使Envoy处于不良状态。如果与管理服务器的联系丢失,则TTL设置允许Envoy在指定的时间段后删除一组资源。例如,当无法再访问管理服务器时,可以使用它来终止故障注入测试。

对于支持xds.config.supports-resource-ttl客户端功能的客户端,可以在每个Resource上指定一个TTL字段。每个资源都有其自己的TTL到期时间,届时该资源将到期。每种xDS类型可能有不同的方式来处理这种到期。

要更新与Resource相关联的TTL ,管理服务器将使用新的TTL重新发送资源。要删除TTL,管理服务器将重新发送未设置TTL字段的资源。

为了允许进行轻量级TTL更新("心跳"),可以发送响应,为 资源提供未 设置资源的资源,并且可以使用与最近发送的版本匹配的版本来更新TTL。这些资源将不被视为资源更新,而仅被视为TTL更新。

## Sotw ttl

为了将TTL与SotW xDS一起使用,必须将相关资源包装在 Resource中。这允许在不更改SotW API的情况下设置用于Delta xDS和SotW的相同TTL字段。SotW也支持心跳:响应中任何看起来像心跳资源的资源都将仅用于更新TTL。

此功能由xds.config.supports-resource-in-sotw客户端功能控制。

## 汇总发现服务

在排序方面提供上述保证,以避免在分发管理服务器时流量下降,这是具有挑战性的。ADS允许单个管理服务器通过单个gRPC流传递所有API更新。这提供了仔细地对更新进行排序以避免流量下降的功能。对于ADS,单个流与通过类型URL多路复用的多个独立的 DiscoveryRequest/DiscoveryResponse序列一起使用。对于任何给定类型的URL,都适用上述DiscoveryRequest和DiscoveryResponse消息的顺序 。示例更新序列可能如下所示:

![在ADS流上多路复用的EDS/CDS](https://www.envoyproxy.io/docs/envoy/latest/_images/ads.svg)

每个Envoy实例都可以使用一个ADS流。

bootstrap.yamlADS配置的最小片段示例是:

node: id:  dynamic\_resources: cds\_config: {ads: {\}} lds\_config: {ads: {\}} ads\_config: api\_type: GRPC grpc\_services: envoy\_grpc: cluster\_name: ads\_cluster static\_resources: clusters:

*   name: ads\_cluster

    connect\_timeout: { seconds: 5 }

    type: STATIC

    hosts:

    *   socket\_address:

        &#x20; address:&#x20;

        &#x20; port\_value:&#x20;

        lb\_policy: ROUND\_ROBIN

        **It is recommended to configure either HTTP/2 or TCP keepalives in order to detect**

        **connection issues, and allow Envoy to reconnect. TCP keepalive is less expensive, but**

        **may be inadequate if there is a TCP proxy between Envoy and the management server.**

        **HTTP/2 keepalive is slightly more expensive, but may detect issues through more types**

        **of intermediate proxies.**

        http2\_protocol\_options:

        connection\_keepalive:

        &#x20; interval: 30s

        &#x20; timeout: 5s

        upstream\_connection\_options:

        tcp\_keepalive:

        &#x20; ...

        admin:

        ...

        **增量xDS**

增量xDS是一个单独的xDS端点,该端点:

* 允许协议根据资源/资源名称增量(" Delta xDS")在线路上进行通信。这支持xDS资源可伸缩性的目标。管理服务器只需要交付已更改的单个集群,而不是在修改单个集群时交付所有10万个集群。
* 允许envoy按需/延迟请求其他资源。例如,仅在对集群的请求到达时才请求集群。

增量xDS会话始终在gRPC双向流的上下文中。这使xDS服务器可以跟踪与其连接的xDS客户端的状态。尚无REST版本的增量xDS。

在增量xDS有线协议中,现时字段是必填字段,用于将DeltaDiscoveryResponse 与DeltaDiscoveryRequest ACK或NACK配对。(可选)存在响应消息级别system\_version\_info ,仅用于调试目的。

可以在以下情况下发送DeltaDiscoveryRequest:

* xDS双向gRPC流中的初始消息。
* 作为对先前DeltaDiscoveryResponse的ACK或NACK响应。在这种情况下,response\_nonce在响应中设置为现时值。ACK或NACK取决于error\_detail的存在与否。
* 来自客户端的自发DeltaDiscoveryRequests。可以这样做以从跟踪的resource\_names集中动态添加或删除元素。在这种情况下,必须省略response\_nonce。

在该第一示例中,客户端连接并接收其确认的第一更新。第二次更新失败,客户端NACK更新。之后,xDS客户端自发请求" wc"资源。

![增量会话示例](https://www.envoyproxy.io/docs/envoy/latest/_images/incremental.svg)

重新连接时,增量xDS客户端可以告知服务器其已知资源,以避免通过网络重新发送它们。因为假定没有状态保留在先前的流中,所以重新连接的客户端必须向服务器提供其感兴趣的所有资源名称。

![增量重新连接示例](https://www.envoyproxy.io/docs/envoy/latest/_images/incremental-reconnect.svg)

## 资源名称

资源由资源名称或别名标识。资源的别名(如果存在)可以通过DeltaDiscoveryResponse资源中的别名字段进行标识。资源名称将在DeltaDiscoveryResponse资源的名称字段中返回 。

## 订阅资源

客户端可以在DeltaDiscoveryRequest的resource\_names\_subscribe字段中发送别名或资源名称, 以便订阅资源。应该同时检查资源的名称和别名,以确定有关实体是否已订阅。

一个resource\_names\_subscribe字段可以包含资源名称,服务器认为客户端已经订阅了,并且还具有的最新版本。但是,服务器仍必须在响应中提供这些资源。由于隐藏在服务器上的实现详细信息,尽管明显保留了订阅资源,客户端仍可能"忘记了"那些资源。

## 退订资源

当客户对某些资源失去兴趣时,它将使用DeltaDiscoveryRequest的resource\_names\_unsubscribe字段进行 指示。与resource\_names\_subscribe一样,它们可以是资源名称或别名。

一个resource\_names\_unsubscribe字段可能包含多余的资源名称,该服务器认为客户端已经没有订阅。服务器必须彻底处理此类请求；它可以简单地忽略这些幻像取消订阅。

## 知道何时不存在所请求的资源

当客户端预订的资源不存在时,服务器将发送一个资源,该资源的名称字段与客户端预订的名称匹配,并且资源 字段未设置。这使客户端可以快速确定何时不存在资源,而无需等待超时,就像在SotW协议变体中所做的那样。但是,仍然鼓励客户端使用超时来防止管理服务器未能及时发送响应的情况。
