kitex
kitex copied to clipboard
Proposal: Kitex support xDS Protocol
背景
希望 Kitex 能够原生支持 xDS 协议 ,让 Kitex 服务能够以 Proxyless 的模式被服务网格统一纳管,从而丰富网格数据面部署架构形态,让用户可以在不同场景下有更多更适合特定场景的部署形态选择
目标
- 完成 Kitex 对接 xDS 之后整体架构形态设计
- 完成 Kitex 框架治理能力如何适配 xDS 模型的概要设计
设计介绍
整体架构

整体主要有几个模块组成:
- Control Plane:控制面,负责管理数据面并基于 xDS 协议下发治理规则
- Kitex Application:Kitex 内部整体主要分为两层
- xDS 层:
- xDS Client:封装基于 xDS 协议与控制面交互逻辑
- xDS Resource Manger:管理 xDS 各协议资源的缓存,并对外提供发布订阅能力
- 治理能力层:基于框架提供的治理能力拓展机制,来适配 xDS 模型,实现各种数据面治理能力
- xDS 层:
框架治理能力适配
为了对接治理能力,框架需要做的适配包括以下几部分:
- [x] 添加
RouterMW,顺序在内置中间件的第一位(动态路由后才能确定之后的配置)。 - [x] 扩展
Resolver接口实现XdsResolver,判断服务发现类型,基于 eds 获取实例信息。 - [ ] 扩展
LoadBalancer接口实现XdsLoadbalancer,根据 cds 动态调整负载均衡策略。
各种治理能力适配思路如下
1. 服务注册
Istio 虽然本身不提供服务注册中心,但是内部维护了统一的服务模型和服务注册表,并且支持集成两种类型的服务注册中心 Provider
- Kubernetes:基于 K8S APIServer List-Watch ,注册并发现 Kubernetes 上的服务
- External:注册并发现外部服务,其中外部服务以 ServiceEntries 的形式定义,可以直接 ServiceEntry CRD 描述,也可以通过 MCP-over-xDS 的方式,以外部数据源的方式注册进来
因此,我们在该方案中无需去设计并实现一套服务注册流程了,只需要直接去对接现有的服务注册中心即可。
2. 动态路由
流程大致如下所示:

- 增加一个 xDS Router MW 来负责 Pick Cluster(路由),watch 目标服务的 LDS 及 RDS
- 感知 LDS 变化,并提取目标服务的 LDS 中的 Filter Chain 及其 inline RDS
- 感知 RDS 变化,根据 VirtualHost 和 ServiceName 来匹配(支持前缀、后缀、精确、通配),获取目标服务的路由配置
- 遍历处理匹配到的 RDS 中的路由规则,路由规则主要分为两部分(参考:路由规范定义):
- Match(支持前缀、后缀、精确、通配等),目前版本我们支持以下两种即可: 1. Path(必须项):从 rpcinfo 提取 Method进行匹配 2. HeaderMatcher(可选项):可自定义需要匹配的元数据,比如 metainfo 内的 key-value。
- Route: 1. Cluster:标准 Cluster 2. WeightedClusters(权重路由):MW 内根据权重来选择 cluster 3. 将选择到的 Cluster 写入 EndpointInfo.Tag,用于之后的服务发现。
3. 服务发现
基于 Kitex 的 Resolver 接口,拓展一个 XDSResolver 来进行服务发现。
- 根据 RDS 找到对应的 CDS (Pick Cluster)之后,进入 Resolve 阶段,通过根据 CDS 获取对应的 Cluster 配置,包括负载均衡策略、熔断等。之后拉取 EDS 资源以获取实例信息,并根据对应的 LB 策略,pick 出最终的一个 Endpoint。
服务发现类型包括以下几种:
- Static:直接返回实例的地址
- Static DNS:数据面需要执行 DNS 解析,以获得所有的实例信息。(异步、周期性地解析)
- Logical DNS:执行 DNS 解析,只有当需要建立连接时才使用返回实例信息中的第一个。static DNS 的返回结果是完整的实例信息,当两次的结果不同,则需要清理连接。而 logic DNS 则会维持连接,直至被回收。
- EDS:与控制面交互,发送 eds 请求,以获得实例信息。
4. 负载均衡
Lb policy 包含在 CDS 内,所以 lb 策略的变化是在动态路由选定 cluster 之后获取并应用的。 Kitex 支持自定义 LoadBalancer,实际上就是根据lb策略,从服务发现获得的实例列表内选取一个实例进行调用。
type Loadbalancer interface {
GetPicker(discovery.Result) Picker // 之后添加入参ctx
Name() string // unique key
}
如果希望动态调整 lb 策略,需要扩展一个 XDSLoadBalancer 。 在 GetPicker 的实现内完成 lb 策略的获取 (CDS),及不同策略的实现。
5. 超时控制
根据 RDS 中的 timeout 配置来动态调整 RPC Timeout Middleware 的 RPCInfo 中的超时时间即可,实现方式:
- xdsRouterMW 内获取到 timeout 配置,设置到 rpcinfo 的 config 中,之后会被用于请求的超时时间设置。
6. 熔断器
Istio 支持的熔断配置相较于 Kitex 会更丰富些,除了异常检测之外,还额外支持对连接池的控制,并且每种熔断策略支持的可配置项也非常完备
我们这期先支持基础的异常检测熔断策略,大致流程如下:
- 在 xDS Router MW 中,我们完成 Pick Cluster 的同时,也会拿到相应目标 Cluster 的熔断策略,比如连续请求错误个数(这期我们只考虑异常检测这种熔断策略)
- 启用熔断,并调用 CBSuite 的 UpdateServiceCBConfig 和 UpdateInstanceCBConfig 来动态更新 Key 的阈值
7. 重试
RDS 中会携带 retry policy 规则,Kitex 可以根据这个动态调整其客户端重试策略
Hi, @CoderPoet! I am interested in this proposal, is there anything I could help with?
Hi, @CoderPoet! I am interested in this proposal, is there anything I could help with?
Very welcome, I have drawn you into the working group, we will dismantle some tasks later!
Istio 服务发现是基于 Kubernetes 实现的. Istio 控制面中,Pilot 组件负责管理服务网格内部的服务和流量策略。Pilot 将服务信息和路由策略转换为 xDS 接口的标准数据结构,下发到数据面的 Envoy. 个人理解,如果只是简单的应用开发,其实不用考虑 xDS 协议底层到底做了些什么,“应用” 和 “网络” 做到解耦。过不过kitex 能从底层支持 xDS 协议,是最好不过了,这样更贴近“云原生”,在相关场景下的应用会更广泛。
Istio 服务发现是基于 Kubernetes 实现的. Istio 控制面中,Pilot 组件负责管理服务网格内部的服务和流量策略。Pilot 将服务信息和路由策略转换为 xDS 接口的标准数据结构,下发到数据面的 Envoy. 个人理解,如果只是简单的应用开发,其实不用考虑 xDS 协议底层到底做了些什么,“应用” 和 “网络” 做到解耦。过不过kitex 能从底层支持 xDS 协议,是最好不过了,这样更贴近“云原生”,在相关场景下的应用会更广泛。
嗯嗯,对的,目的就是为了丰富网格数据面部署架构形态,让用户可以在不同场景下有更多更适合特定场景的部署形态选择
另外稍微补充下 Kubernetes 只是 istio 的服务注册及发现的其中一种,并作为默认的 provider 存在,其实还可以对接外部注册中心的哈