Indexer
Indexer是一个用来存储资源对象的内存存储,处理用户的查询是非常快速高效的。源码路径为k8s.io/client-go/tools/cache/index.go。
Indexer的实现主要分为2部分,ThreadSafeMap是底层的并发安全存储,Indexer索引器用来注册索引函数。
1.ThreadSafeMap并发安全存储
Indexer是在ThreadSafeMap的基础上进行了封装,ThreadSafeMap使用了读写锁来保证并发的读写安全。ThreadSafeMap的源码路径为k8s.io/client-go/tools/cache/thread_safe_store.go。
ThreadSafeMap的定义示例如下。
type threadSafeMap struct {
lock sync.RWMutex
items map[string]interface{}
indexers Indexers
indices Indices
}
其中items是用来存储资源对象的map,key默认由Meta-NamespaceKeyFunc函数处理后得到,经过处理后的key的格式为namespace/name。items的值用来存储资源对象。
ThreadSafeMap增删改查的入口方法分别是AddIndexers、deleteFromIndices、updateIndices、GetIndexers。这些方法会执行底层针对items的Add、Delete、Update、Get、List等方法。
2.Indexer索引器
Indexer被设计成是一个可以自定义索引函数的索引器,这样方便我们进行自定义扩展,也符合Kubernetes高度可扩展性的需求。
Indexer有4个重要的数据结构来支撑实现自定义索引的特性,示例如下。
type Indexers map[string]IndexFunc
type IndexFunc func(obj interface{}) ([]string, error)
type Indices map[string]Index
type Index map[string]sets.String
·Indexers:map类型,用来存储自定义的索引,key是自定义的索引名,value是索引函数。
·IndexFuc:索引函数。
·Indices:map类型,用来存储缓存器,key是缓存器的名字,value是具体的索引缓存。
·Index:map类型,用来存储缓存数据,key是索引,value是set集合。
下面通过源码中的测试用例函数来了解如何自定义一个索引器的函数,源码路径为k8s.io/client-go/tools/cache/index_test.go,示例如下。
func testIndexFunc(obj interface{}) ([]string, error) { pod := obj.(*v1.Pod) return []string{pod.Labels["foo"]}, nil } func TestGetIndexFuncValues(t *testing.T) { index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"testmodes": testIndexFunc}) pod1 := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "one", Labels: map[string]string{"foo": "bar"}}} pod2 := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "two", Labels: map[string]string{"foo": "bar"}}} pod3 := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "tre", Labels: map[string]string{"foo": "biz"}}} index.Add(pod1) index.Add(pod2) index.Add(pod3) keys := index.ListIndexFuncValues("testmodes") if len(keys) != 2 { t.Errorf("Expected 2 keys but got %v", len(keys)) } for _, key := range keys { if key != "bar" && key != "biz" { t.Errorf("Expected only 'bar' or 'biz' but got %s", key) } } }
·testIndexFunc()是一个自定义的索引器函数,具体功能是通过labels过滤key中包含foo字段的Pod,并返回value。
·NewIndexer()用来初始化一个Indexers索引器,第一个参数是自定义的索引器名字"testmodes",第二个参数是自定义索引器的具体函数testIndexFunc。
·初始化Indexer之后创建了3个Pod资源对象并且label都包含foo字段,通过index.Add()方法存入index,然后执行ListIndexFuncValues()并传入自定义的索引函数名称"testmodes"来获取符合索引规则的值。
这个测试用例下还有一个testUsersIndexFunc自定义索引器函数,并通过TestMultiIndexKeys函数内的index.ByIndex进行测试。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)