首页 > 其他分享 >list watch机制

list watch机制

时间:2023-07-16 10:00:26浏览次数:25  
标签:watch list client ResourceVersion 机制 k8s 数据

3点需求

只需要感知数据最新的状态,不担心错过数据的变化过程。
需求1: 实时性(即数据变化时,相关组件越快感知越好)
需求2: 保证消息的顺序性(即消息要按发生先后顺序送达目的组件。很难想象在Pod创建消息前收到该Pod删除消息时组件应该怎么处理)
需求3: 保证消息不丢失或者有可靠的重新获取机制(比如说kubelet和kube-apiserver间网络闪断,需要保证网络恢复后kubelet可以收到网络闪断期间产生的消息)

需求1的解决方案

k8s组件间主要通过http2协议(k8s 1.5之前采用http1.1,Go1.7之后开始支持http2)进行数据交互。

方案1: http长轮询(etcd2中watch)

client发起http request,服务端有请求数据后回复一个response(如果没有数据,那么服务端就等到有数据再回复),客户端收到response后马上又发起新的request,如此往复。

方案1缺点: 通信消耗大(每个response多一个request)

方案2:分块传输编码(watch,http get请求)

client发起http request,服务端有请求数据就回复一个response(回复的http header中会带上"Transfer-Encoding":"chunked")。client收到这种header的response后会继续等待后续数据,服务端有新的数据时会继续通过这条长连接发数据。

方案2缺点: 需要对返回的数据做定制
k8s选择了方案2。

需求2的解决方案

k8s在ObjectMeta结构体中加了ResourceVersion字段,该字段的值由etcd来保证全局单调递增(每当etcd中写入一个数据时,全局ResourceVersion就加1)。保证不同时刻的数据ResourceVersion不同,并且后产生数据的ResourceVersion较之前数据的ResourceVersion大。client发起watch请求时,只需要带上请求数据在本地缓存中的最新ResourceVersion,server根据ResourceVersion从小到大把大于client ResourceVersion的数据按顺序推送给client,保证了推送数据的顺序性。

因为etcd保证全局单调+1,所以某类数据的RV可能不会逐步+1变化。

需求3的解决方案

基于需求1和需求2的解决方案,需求3主要是对异常状况处理。k8s中结合watch请求增加了list请求。

1. watch请求开始之前,先发起一次list请求,获取集群中当前所有该类数据(同时得到最新的ResourceVersion),之后基于最新的ResourceVersion发起watch请求。
2. 当watch出错时(比如说网络闪断造成client和server数据不同步),重新发起一次list请求获取所有数据,再重新基于最新ResourceVersion来watch。
list-watch流程如下:

具体代码参见: kubernetes/vendor/k8s.io/client-go/tools/cache/reflector.go#ListAndWatch()

watch处理中的ResourceVersion更新是在watchHandler()中实现的。

总结

1. list请求返回全量数据,如果数据量较大时(比如20wPod),如果watch失败后需要relist,这时list请求成本是很高的。(服务端和客户端都需要对20w数据进行编解码,序列化和反序列化等)。k8s大规模应用场景下,需要尽量减少relist发生次数。
2. http1.1时(kubernetes1.5前)因为长连接是独立的TCP连接,假如网络断了,客户端是感知不到网络断开的,只是以为服务端一直没有数据。tcp keep-alive机制检测到网络断开后(golang默认http client的keep-alive时间是30s),会主动reset掉该连接,然后再次建立新的连接。在http2(大于kubernetes1.5中使用)中因为大家共用一条TCP连接,client各种请求导致keep-alive机制无法发挥作用,最后只能由数据的重传超时来reset掉这条TCP连接,这种场景下对系统的影响可能要大一些。
3. k8s 1.5之前http1.1中每个REST资源的list-watch都有一条长连接,这样对服务器压力很大。http2连接复用机制在k8s 1.5后得到了很好的解决。
4. tcp长连接断开考虑: 因为client不清楚服务端是否还有数据需要发送,所以由server来断开。
5. 如果client挂掉,那么server不知道,这样在kubernets1.5之前(因为使用http1.1)server维护大量的无效连接,造成server资源的大量浪费。k8s的解决方案是: watch请求中带一个超时参数(TimeoutSeconds),默认为5~10min间的随机数。所以server只要超时时间一到就会断开连接。server断开连接,time_wait将砸在server的手里。而time_wait的有效时间为1min~4min,所以5~10min是一个比较好的选择,可以保证server的time_wait保持在一个比较稳定的数量。
k8s采用了基于level trigger(条件触发,只要满足条件就发生)而非edge trigger(边缘触发,每当状态变化时发生)的设计理念,没有额外引入MQ,降低了系统的整体复杂度。

参考资料

【Sigma敏捷版系列文章】从运行流程和list-watch看kubernetes系统的设计理念

标签:watch,list,client,ResourceVersion,机制,k8s,数据
From: https://www.cnblogs.com/WJQ2017/p/17557481.html

相关文章

  • window.onload && window.addEventListener 区别
    window.onload&&window.addEventListener区别关于本节提到的:window.addEventListener('load',function(){alert('word')})window.onload=function(){alert('hello')}执行顺序addEventListener比onload先执行a......
  • [gym102770L]List of Products
    题意简述我们根据唯一分解定理得到,对于每一个数\(x\)可以表示成\(\sump_i^{e_i}\)的形式,其中\(p_i\)表示第\(i\)大的素数。我们重新定义两个数之间的比较,对于两个数\(x,y\):如果\(x=y\),两个数相等如果\(x,y\)不相等,我们就从小到大枚举素数,知道找到一个下标......
  • vue-day16---watch与computed实现列表过滤
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width,initial-scale=1.0"/><title>watch与computed实现列表过滤</title>......
  • antd table提示Warning: Each child in a list should have a unique "key" prop.
    参考:表中的每条记录都应该有一个唯一的“key”属性,或者将“rowKey”设置为唯一的主键。·问题#7623·ant-design/ant-design解决<Tablecolumns={columns}dataSource={this.props.categories}rowKey="name"/>原因:column没有指定key,那就在表中指定下其他解......
  • python 多层list遍历
    Python多层列表遍历指南作为一名经验丰富的开发者,我很高兴能够帮助你学习如何在Python中实现多层列表的遍历。在本篇文章中,我将向你介绍整个遍历过程的流程,并为每一步提供相应的代码示例和注释。目录准备工作多层列表的遍历方法示例代码总结1.准备工作在开始之前,确保......
  • pythonlist添加一行
    PythonList添加一行的实现方法一、整体流程为了帮助刚入行的小白理解如何实现“PythonList添加一行”,我们可以使用以下步骤进行解释:步骤描述1创建一个空的列表2定义要添加的新行3使用列表的append()方法将新行添加到列表中4打印列表以验证添加的行......
  • Spartacus Product List Page ProductSearchPage Observable 对象的设计明细
    源代码如下:readonlymodel$:Observable<ProductSearchPage>=using(()=>this.searchByRouting$.subscribe(),()=>this.searchResults$).pipe(shareReplay({bufferSize:1,refCount:true}));上面这段代码是基于Angular框架和RxJS库的,RxJS是一个用于处理......
  • 关于 Spartacus ProdutList Component Service model$ 的填充逻辑
    源代码:这段代码是Angular中的RxJS代码,主要是创建一个名为model$的Observable对象,这个对象的生成逻辑复杂一些,主要涉及using,subscribe,pipe,shareReplay等函数的使用。逐行解释如下:readonlymodel$:Observable<ProductSearchPage>=using(这一行定义了一个......
  • cpp class constructor initialize list and override cout
    //book.h#pragmaonce#include<iostream>classbook{public:intidx;std::uint64_tid;std::stringauthor;std::stringcontent;std::stringcomment;std::stringisbn;std::stringsummary;std::stringtopic;boo......
  • Python - list VS tuple, list() VS []
    差异一:list可变vstuple不可变列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素(mutable)。而元组是静态的,长度大小固定,无法增加删减或者改变(immutable)。#Jupyter格式tup=(1,2,3,4)new_tup=tup+(5,)#创建新的元组new_tup,并依次填充原元组的值new_......