(译)xDS REST and gRPC protocol
xDS REST and gRPC protocol
原文地址:xDS REST and gRPC protocol.
envoy可通过文件系统、一个或多个管理服务器来发现各种动态资源.这些服务发现和他们相对应的API统称为xDS.通过定阅方式获取资源,如监控指定的文件路径、gRPC流或轮询REST-JSON URL.后两种使用DiscoveryRequest来发送请求消息.所有的资源包含在DiscoveryResponse响应消息中.下面,我们将讨论每种订阅类型.
文件订阅
动态配置最简单的方法是将配置写入一个文件,文件路径通过ConfigSource配置.Envoy会使用inotify(Mac OS X上用kqueue)去监控文件的变化,文件更新时用DiscoveryResponse进行解析.DiscoveryResponse支持的格式包括: 二进制protobuf,JSON,YAML和协议文本.
文件订阅支持统计数据和日志,不支持ACK/NACK的更新方式.如果配置更新被拒绝,xDS API将使用最近一次的有效配置.
gRPC流订阅
单资源类型发现
gRPC ApiConfigSource对于xDS API都可单独配置,指向对应的上游管理服务器的集群地址.每种xDS资源类型都会各自启动一个双向的gRPC流,来对应可能会向不同的管理服务器发起.API的交付方式是最终一致性的.明确控制的顺序可看下面的ADS.
URL类型
每个xDS API都与特定的资源类型相关.xDS API和资源类型之间是1:1的.对应关系如下:
- LDS: envoy.api.v2.Listener
- RDS: envoy.api.v2.RouteConfiguration
- CDS: envoy.api.v2.Cluster
- EDS: envoy.api.v2.ClusterLoadAssignment
- SDS: envoy.api.v2.Auth.Secret
URL类型的概念如下所示,其采用type.googleapis.com/<resource type>形式,例如: CDS对应于type.googleapis.com/envoy.api.v2.Cluster.在 Envoy 的请求和管理服务器的响应中,都包括了资源类型 URL.
ACK/NACK和版本控制
每个Enovy以流DiscoveryRequest开始,包括指定订阅资源列表,订阅资源对应的URL类型,结点标志和空version_info.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应答之后,将通过流发送一个新请求,请求包括应用成功的最后一个版本号和管理服务器提供的nonce.如果这次更新成功应用,version_info将被设置为X,时序图如下:

在此序列图及后续中,将统一使用以下缩写格式:
DiscoveryRequest: (V=version_info,R=version_info,N=response_nonce,T=type_url)DiscoveryResponse: (v=version_info,R=resources,N=nonce,T=type_url)
版本为Envoy和管理服务器提供了共享当前应用配置的概念以及通过ACK/NACK来进行配置更新.如果Envoy拒绝配置更新X,它将返回error_detail和上一个版本号,在当前情况下为空的初始版本号.error_detail包含了更多的错误详细信息:

后续,API可能会在版本Y上更新成功:

每个流都有自己的版本,跨资源类型没有共享版本.当不使用ADS时,甚至每个资源类型都可能有不同的版本,因为Envoy API允许不同的EDS/RDS资源配置对应不同的ConfigSource.
何时发送更新
管理服务器仅在DiscoveryResponse更改资源时才向Envoy客户端发送更新.Envoy会根据接受和拒绝的情况,会立即回复包含ACK/NACK的请求.如果管理服务器每次发送相同的资源集而不是等到有改变时再发送,这会导致Envoy和管理服务器的效率大打折扣.
对于同个流,新的DiscoveryRequest将取代之前具有相同的资源类型请求.这意味着管理服务器只响应最新DiscoveryRequest的请求,在相同的资源请求下.
资源提示
DiscoveryRequest中resource_names作为资源提示出现.一些资源类型,例如:cluster和listener将使用一个空的resource_names列表.因为Envoy需要获取管理服务器对应于节点标识的所有Clusters(CDS)和Listeners(LDS).对于其它的资源类型,例如:RouteConfigurations(RDS)和ClusterLoadAssignments(EDS),遵循早期的CDS/LDS更新,Envoy能够明确地列举这些资源.
LDS和CDS资源信息始终为空,并且期望管理服务器将在每个响应中提供LDS / CDS资源的完整状态.缺席的Listener或Cluster将被删除.resource_names只是一个提示.
对于EDS/RDS,管理服务器不需要提供每个资源的请求,也可能提供额外的未请求资源.Envoy会忽略多余的资源信息.当一个RDS或EDS的更新缺少请求资源时,Envoy将会保留对应资源最后的有效值.管理服务器可能能够从node标识中推断出所有所需的EDS/ RDS资源DiscoveryRequest,在这种情况下,提示信息可能会被丢弃.从特定角度看,一个空的EDS/RDS DiscoveryResponse响应说明Envoy是一个空的资源.
当Listener或Cluster被删除,Envoy上相应EDS和RDS资源也会被删除.为了让Envoy知道或跟踪EDS资源,必须存在应用过的Cluster定义(例如:通过CDS获得).RDS和Listeners之间也存在相似的关系(通过LDS获得).
对于EDS/RDS,Envoy可以为每个给定类型的资源生成不同的流(如每个ConfigSource都有自己的上游管理服务集群)或当指定资源类型的请求发送到同一个管理服务器的时候,允许将多个资源请求组合在一起发送.虽然可以单个实现,但管理服务器应该能够为resource_names每个请求中的给定资源类型处理一个或多个.下面的两个时序图都可用于获取两个EDS资源{foo, bar}:


资源更新
如上所述,Envoy可能会更新resource_names列表在每个DiscoveryRequest,其中DiscoveryResponse是用来ACK/NACK管理服务器的特定的.此外,Envoy 后续可能会发送额外的DiscoveryRequest,用于在特定version_info上使用新的资源提示来更新管理服务器.举个例子: 如果Envoy在EDS版本X时仅知道集群foo,但随后收到一个CDS更新时额外获取了集群bar,它可能会为版本X发出额外的DiscoveryRequest请求,并将{foo,bar}作为请求的resource_names.

这里可能会出现竞争情况;如果Envoy在版本X上发布了资源提示更新请求,但在管理服务器处理该请求之前发送了新的版本号为Y的响应,对于version_info为X的版本,资源提示更新可能会被解释为拒绝Y.为了避免这种情况,管理服务器提供nonce,Envoy可以用来保证DiscoveryResponse对应每个DiscoveryRequest.

管理服务器不应发送DiscoveryResponse响应给任何过期DiscoveryRequest请求.Envoy在DiscoveryResponse响应中包含了新的nonce,而旧的nonce将过期做废.在新的版本就绪前,管理服务器不需要发送更新.同版本的早期请求也会过期.在新版本就绪时,管理服务器可能会处理同版本的多个DiscoveryRequests请求.

上述资源更新时序图表明Envoy 并不能期待其发出的每个DiscoveryRequest请求都能得到DiscoveryResponse响应.
最终一致性考虑
由于Envoy xDS API采用最终一致性,在更新期会导致流量丢失.举个例子: 如果通过CDS/EDS仅获取到了集群X,而且RouteConfiguration引用了集群X,在CDS/EDS更新集群Y配置之前,如果将集群调整为Y,那么流量将被丢弃,直到集群Y被Envoy实例获取.
对某些应用程序,暂时的流量丢失是可接受的,客户端重试或其它的Envoy sidecar会掩盖这这些丢失.对于对流量丢失不能容忍的场景,可以通过以下方式避免流量丢失.CDS/EDS更新同时携带X和Y,然后发送RDS更新从X切换到Y,最后发送丢弃X的CDS/EDS更新.
通常情况下,为了避免流量丢失,更新的顺序应该遵循make before break模型,其中
- 必须始终先推送CDS更新(如果有).
- EDS更新(如果有)必须在相应群集的CDS更新后到达.
- LDS更新必须在相应的CDS/EDS更新后到达.
- 与新添加的监听器相关的RDS更新必须最终到达.
- 删除过期的CDS群集和相关的EDS端点(不再被引用的端点).
如果没有新的集群/路由/监听器或者允许更新时临时流量丢失的情况下,可以单独推送xDS更新.请注意,在LDS更新的情况下,监听器须在接收流量之前被预热,例如: 如果配置了依赖的路由,则需先从RDS获取规则.添加/删除/更新集群信息时,集群也要进行预热.另一方面,路由可以不用预热,例如: 管理平面确保在更新路由时,集群中的路由已经就绪.
聚合服务发现(ADS)
当管理服务器进行分发时,通过上述保证交互顺序的方式来避免流量丢失是一项很有挑战的工作.ADS允许单一管理服务器,通过gRPC流的方式来分发所有的API更新.配合仔细规划的更新顺序,ADS可规避更新过程中流量丢失.使用ADS,在单个流上可通过URL类型来进行复用多个独立的DiscoveryRequest/DiscoveryResponse序列.对于任何给定类型的URL,以上的DiscoveryRequest和DiscoveryResponse消息序列都适合.一个更新的时序图如下:

对于每个Envoy实例,ADS流都是可用的.
最小化ADS配置的bootstrap.yaml片段示例如下:
node:
id: <node identifier>
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:
address: <ADS management server IP address>
port_value: <ADS management server port>
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
admin:
...
增量xDS
增量xDS是可用于允许的ADS、CDS和RDS的单独xDS端点:
- xDS客户端对跟踪资源列表进行增量更新.这支持Envoy按需/惰性地请求额外资源.举个例子: 当与未知集群相对应的请求到达时,这是有可能发生的.
- xDS服务端可以增量更新客户端上的资源.这支持xDS资源可伸缩性的目标.管理服务器只需发送给更改的单个集群,而不是在修改单个集群时发送给所有100k集群.
xDS增量会话始终位于gRPC双向流的上下文中.这允许xDS服务器能够跟踪到连接的xDS客户端的状态.xDS REST版本不支持增量.
在增量xDS中,nonce字段是必须的,用于匹配IncrementalDiscoveryResponse与IncrementalDiscoveryRequest关联的ACK或NACK.可选地,响应级别的消息system_version_info仅用来调试.
IncrementalDiscoveryRequest在以下3种情况发送:
- 在一个双向gRPC流初始化消息.
- 作为对先前的
IncrementalDiscoveryResponse的ACK或NACK响应.这种情况下,response_nonce将在响应中被设为nonce值.ACK或NACK存不存在由error_detail确定. - 由客户自发.可以动态地添加或删除被跟踪
resource_names集.在这种情况下,response_nonce必须被忽略.
在第一个示例中,客户端连接并接收它的第一个更新并ACK,第二次更新失败,客户发送NACK拒绝更新,然后xDS客户端会自发的请求"wc"资源.

在重新连接时,增量的xDS客户端可能会告诉服务器其已有资源从而避免通过网络重新发送它们.

轮询REST-JSOM URL订阅
通过REST端点进行同步(长)轮询,也可用于xDS单例API.和上面的消息序列类似,除了在管理服务器没有保持一个永久的流.在任何时间点只有一个未完成的请求,因此响应现时在REST-JSON中是可选的.proto3的Json编码规范用于编码DiscoveryRequest和DiscoveryResponse消息.ADS不适用REST-JSON轮询.
当轮询周期设置为较小的值时,为了进行长轮询,则还需要避免发送DiscoveryResponse,除非对底层资源进行了更改.
(译)xDS REST and gRPC protocol的更多相关文章
- Go微服务实战 - 用户服务开发(gRPC+Protocol Buffer)
概要 用户服务基本是每个互联网产品里必备的一个服务了,因为没有用户基本是什么也干不了.所以他的重要性不言而喻.本文主要介绍下如何开发一个用户微服务,以及他的详细开发流程. 目录 Go微服务实战 - 从 ...
- Istio流量管理实现机制深度解析
https://zhaohuabing.com/post/2018-09-25-istio-traffic-management-impl-intro/TOC 前言 Pilot高层架构 统一的服务模型 ...
- 深入理解Istio核心组件之Pilot
Istio作为当前服务网格(Service Mesh)领域的事实标准,流量治理(Traffic Management)是其最为基础也最为重要的功能.本文将结合源码对Istio流量治理的实现主体——组件 ...
- 新手学分布式 - Envoy Proxy XDS Server动态配置的一点使用心得
Envoy Proxy 动态API的使用总结 Envoy Proxy和其它L4/L7反向搭理工具最大的区别就是原生支持动态配置. 首先来看一下Envoy的大致架构 从上图可以简单理解:Listener ...
- springboot2 + grpc + k8s + istio
项目情况说明: ubuntu - 16.04 springboot - 2.2.2.RELEASE mysql - 5.7 mongodb - 4.0.14 redis - 3.0.6 grpc - ...
- Istio中的流量配置
Istio中的流量配置 目录 Istio中的流量配置 Istio注入的容器 Istio-init istio-proxy Envoy架构 Pilot-agent生成的初始配置文件 Envoy管理接口获 ...
- NetCore开源项目集合
具体见:https://github.com/thangchung/awesome-dotnet-core 半年前看到的,今天又看到了,记录下. 框架类: ZKWeb ABP General ASP. ...
- 11 Go 1.11 Release Notes
Go 1.11 Release Notes Introduction to Go 1.11 Changes to the language Ports WebAssembly RISC-V GOARC ...
- 09 Go 1.9 Release Notes
Go 1.9 Release Notes Introduction to Go 1.9 Changes to the language Ports ppc64x requires POWER8 Fre ...
随机推荐
- SpringMVC Maven项目 java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServle
今天在搭建SpringMVC开发框架时,遇到了一个问题,尽管在maven的POM.xml文件中配置了项目所依赖的jar包,但在启动项目是已然报错如下: 信息: Starting Servlet Eng ...
- 退出unity运行
public void GetExit()//退出运行 { #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false;//用于退 ...
- Eclipse Error Reporting Welcome to the Eclipse Error Reporting Service.Do you want to help Eclipse? Enable Disable
在开发的时候,使用Eclipse IDE,提示如下信息, 这是Eclipse的错误报告,如果不想发送,可以关闭掉,关闭方法: 选择Preferences -> General -> Err ...
- 雾霾天出行,如何精确避开“雷区”?2016 SODA数据侠十强
(2016年参加了上海 SODA 竞赛,进入前十,最终获得上海市的两个奖项.) ▍跟踪雾霾,仅靠零星的监测点数据怎么行? 如果雾霾短期内没有办法彻底根治,我们可以做什么,把环境污染物对人的影响尽可能降 ...
- 02:openf-falcon安装
open-falcon其他篇 目录: 1.1 安装open-falcon环境准备 1.2 部署open-falcon后端 1.2.1 agent配置文件 1.2.2 transfer(数据上报) 1. ...
- [c/c++] programming之路(17)、高级指针
一.二级指针 二级指针的作用:1.函数改变外部变量指针2.外挂改变一个指针的值 #include<stdio.h> #include<stdlib.h> void main() ...
- koa2 中 cookie 存在的中文问题
koa2 中的 cookie 没办法直接设置中文,会报错 ‘ argument value is invalid ’ 解决办法: 先将它转成 ‘ base64 ’ 编码来存储 new Buffer( ...
- npm 清理缓存
npm cache clean -f 有些时候npm下载资源出错,再次下载的时候可能因为之前错误的缓存造成一直下载不成功. 此时可以清一下npm的缓存,然后尝试重新下载
- 整型 布尔值 字符串 for循环
1.整型 2.布尔值 3.字符串 4.for循环 1.整型:.python中有长整型, Python3中只有整型 2.布尔值: bool:Ture 真 False 假 数字和布尔值可进行转 ...
- 剑指offer(33)丑数
题目描述 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 题目分析 ...