zl程序教程

您现在的位置是:首页 >  后端

当前栏目

api-server到etcd怎么保证事件不丢失? list-watch有两部分组成,分别是list和watch

server事件ListAPI 怎么 部分 丢失 保证
2023-09-11 14:20:30 时间

1、依赖于K8s组件中的Etcd分布式数据库存储集群信息,任何操作都是通过apiserver来修改Etcd的,其它
组件不可以直接与Etcd通信

客户端(kubelet/scheduler/controller-manager)通过list-watch监听apiserver中资(pod/rs
/rc等等)的create,update和delete事件,并针对事件类型调用相应的事件处理函数。

2、list-watch有两部分组成,分别是list和watch。

list:调用资源的list API罗列资源,基于HTTP短链接实现;
watch:调用资源的watch API监听资源变更事件,基于HTTP 长链接实现;


K8S的informer模块封装list-watch API,用户只需要指定资源,编写事件处理函数,
AddFunc,UpdateFunc和DeleteFunc等。informer首先通过list API罗列资源,然后
调用watch API监听资源的变更事件,并将结果放入到一个FIFO 队列,队列的另一头有
协程从中取出事件,并调用对应的注册函数处理事件。

注意:Informer还维护了一个只读的Map Store缓存,提升查询的效率,降低apiserver负载。

四个要素:
消息可靠性
消息实时性
消息顺序性
高性能

1、可靠性:
list和watch一起保证了消息的可靠性,避免因消息丢失而造成状态不一致场景。list API可以查询当前
的资源及其对应的状态(即期望的状态),客户端通过拿期望的状态和实际的状态进行对比,纠正状态不一致
的资源。Watch API和apiserver保持一个长链接,接收资源的状态变更事件并做相应处理。如果仅调用
watch API,若某个时间点连接中断,就有可能导致消息丢失,所以需要通过list API解决消息丢失问题。
我们可以认为list API获取全量数据,watch API获取增量数据。虽然仅仅通过轮询list API,也能达到
同步资源状态的效果,存在上面提到轮询的缺点:开销大,实时性不足的问题。
(也就是说list机制用于辅助修正)

2、实时性:
list-watch机制下,每当apiserver的资源产生状态变更事件,都会将事件及时的推送给客户端,从而保证
消息的实时性。

3、顺序性:
在并发的场景下,客户端在短时间内可能会收到同一个资源的多个事件,对关注最终一致性的K8S来说,它需
要知道哪个是最近发生的事件,并保证资源的最终状态如同最近事件所表述的状态一样。K8S在每个资源事件
中都带一个resourceVersion的标签,这个标签是递增的数字,所以当客户端并发处理同一个资源事件时,
它就可以对比resourceVersion来保证最终的状态和最新的事件所期望的状态保持一致。
(客户端就通过resrouceVersion来确定数据是不是处于同一时间版本)

4、高性能:
List-watch通过异步通知达到高性能的特点,因为虽然仅通过周期性调用list API也能达到资源最终一致
性的效果,但是周期性频繁的轮询大大的增大了开销,增加apiserver的压力。而watch作为异步消息通知
机制,复用一条长链接,保证实时性的同时也保证了性能。

 

Etcd通过异常重试机制,来保证watch特性的可靠性,在网络波动以及高CPU负载情况下,依然可以不丢失watch事件;

如果在处理slow watch期间,etcd进程重启了,client端会收到什么结果呢?client应该如何应对呢?

serverWatchStream如果给每一个watcher都维护一个channel,那么当watcher数量很大时,会不会占用etcd大量内存呢?

 

二、Watch事件通知模式

1.Etcd v2 轮询

Etcd v2 Watch机制采用HTTP/1.x实现,每个Watcher对应一个TCP连接。Client通过HTTP/1.x长连接定时轮询Server,获取最新的数据变化事件;

这种实现的好处是简单,但是这种机制有一个致命缺点,Watcher数量很多时,就算集群空负载,大量轮询也会导致Server消耗大量的Socket,内存等资源,导致Etcd的扩展性和稳定性无法满足K8s业务场景;

2.Etcd v3 流式推送

Etcd v3基于HTTP/2的gRPC协议,双向流的Watch API设计,实现了连接多路复用。一个client/TCP连接支持多个gRPC Stream,一个gRPC Stream又支持多个Watcher ,同时事件通知模式也从client轮询优化为server流式推送,极大降低server端Socker、内存等资源 。

三、Watch可靠性

Client和Server出现网络抖动后、导致Server时间堆积时,Server会丢弃事件吗?若监听的历史版本号Server端不存在了,你的代码要如何处理?

弄清楚可靠性,先要了解Watch特性的整体架构和核心流程。