// `*cache` implements Indexer in terms of a ThreadSafeStore and an
// associated KeyFunc.
typecachestruct{// cacheStorage bears the burden of thread safety for the cache
cacheStorageThreadSafeStore//一個 thread safe 的 interface
// keyFunc is used to make the key for objects stored in and retrieved from items, and
// should be deterministic.
keyFuncKeyFunc//計算object key的方法,稍後會解釋
}
// NewStore returns a Store implemented simply with a map and a lock.
funcNewStore(keyFuncKeyFunc)Store{return&cache{cacheStorage:NewThreadSafeStore(Indexers{},Indices{}),keyFunc:keyFunc,}}// NewIndexer returns an Indexer implemented simply with a map and a lock.
funcNewIndexer(keyFuncKeyFunc,indexersIndexers)Indexer{return&cache{cacheStorage:NewThreadSafeStore(indexers,Indices{}),keyFunc:keyFunc,}}
// Add inserts an item into the cache.
func(c*cache)Add(objinterface{})error{//透過 key function 計算出 object 所對應的 key
key,err:=c.keyFunc(obj)iferr!=nil{returnKeyError{obj,err}}//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Add function 這裡的細節可以去上章節複習。
//簡單來說就更新 local cache 的物件以及更新 indices 以及 index
c.cacheStorage.Add(key,obj)returnnil}
Update
1
2
3
4
5
6
7
8
9
10
11
12
// Update sets an item in the cache to its updated state.
func(c*cache)Update(objinterface{})error{//透過 key function 計算出 object 所對應的 key
key,err:=c.keyFunc(obj)iferr!=nil{returnKeyError{obj,err}}//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Update function 這裡的細節可以去上一章節複習。
//簡單來說就更新 local cache 的物件以及更新 indices 以及 index
c.cacheStorage.Update(key,obj)returnnil}
Delete
1
2
3
4
5
6
7
8
9
10
11
12
// Delete removes an item from the cache.
func(c*cache)Delete(objinterface{})error{//透過 key function 計算出 object 所對應的 key
key,err:=c.keyFunc(obj)iferr!=nil{returnKeyError{obj,err}}//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Delete 這裡的細節可以去上一章節複習。
//簡單來說就刪除 local cache 的物件以及更新 indices 以及 index
c.cacheStorage.Delete(key)returnnil}
List
1
2
3
4
5
6
7
// List returns a list of all the items.
// List is completely threadsafe as long as you treat all items as immutable.
func(c*cache)List()[]interface{}{//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore List 這裡的細節可以去上一章節複習。
//簡單來說就是列出 local cache 所有 Object
returnc.cacheStorage.List()}
ListKeys
1
2
3
4
5
6
7
// ListKeys returns a list of all the keys of the objects currently
// in the cache.
func(c*cache)ListKeys()[]string{//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore ListKeys 這裡的細節可以去上一章節複習。
//簡單來說就是列出 local cache 所有 Object Key
returnc.cacheStorage.ListKeys()}
GetIndexers
1
2
3
4
5
6
// GetIndexers returns the indexers of cache
func(c*cache)GetIndexers()Indexers{//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore GetIndexers 這裡的細節可以去上一章節複習。
//簡單來說就是列出 loacl cache 目前有的所有 Indexer
returnc.cacheStorage.GetIndexers()}
Index
1
2
3
4
5
6
7
// Index returns a list of items that match on the index function
// Index is thread-safe so long as you treat all items as immutable
func(c*cache)Index(indexNamestring,objinterface{})([]interface{},error){//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Index 這裡的細節可以去上一章節複習。
//簡單來說就是透過以知道的index name 以及 Object 合作幫忙分類列出 loacl cache 相關的 Object
returnc.cacheStorage.Index(indexName,obj)}
List
1
2
3
4
5
func(c*cache)IndexKeys(indexName,indexKeystring)([]string,error){//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore IndexKeys 這裡的細節可以去上一章節複習。
//簡單來說就是透過已知道 index name 以及 indexkey 合作幫忙分類列出 loacl cache 上相關的 Objecy Key
returnc.cacheStorage.IndexKeys(indexName,indexKey)}
List
1
2
3
4
5
6
// ListIndexFuncValues returns the list of generated values of an Index func
func(c*cache)ListIndexFuncValues(indexNamestring)[]string{//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore ListIndexFuncValues 這裡的細節可以去上一章節複習。
//簡單來說就是透過已知道 index name 幫忙分類列出 loacl cache 上負責計算Object key 的名字也就是 indexed function name
returnc.cacheStorage.ListIndexFuncValues(indexName)}
ByIndex
1
2
3
4
5
func(c*cache)ByIndex(indexName,indexKeystring)([]interface{},error){//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore ByIndex 這裡的細節可以去上一章節複習。
//簡單來說就是透過已知道 index name 以及 index key 合作幫忙分類列出 loacl cache 上所有有關的 Object
returnc.cacheStorage.ByIndex(indexName,indexKey)}
// Get returns the requested item, or sets exists=false.
// Get is completely threadsafe as long as you treat all items as immutable.
func(c*cache)Get(objinterface{})(iteminterface{},existsbool,errerror){//透過 key function 計算出 Object 所代表的 object key
key,err:=c.keyFunc(obj)iferr!=nil{returnnil,false,KeyError{obj,err}}//使用該 Object key 來取得 Object
returnc.GetByKey(key)}
GetByKey
1
2
3
4
5
6
7
8
// GetByKey returns the request item, or exists=false.
// GetByKey is completely threadsafe as long as you treat all items as immutable.
func(c*cache)GetByKey(keystring)(iteminterface{},existsbool,errerror){//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Get 這裡的細節可以去上一章節複習。
//簡單來說就是使用 Object key 從 local stoarge 取得相關的 Object
item,exists=c.cacheStorage.Get(key)returnitem,exists,nil}
ReplaceList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Replace will delete the contents of 'c', using instead the given list.
// 'c' takes ownership of the list, you should not reference the list again
// after calling this function.
func(c*cache)Replace(list[]interface{},resourceVersionstring)error{// 傳入一堆 object 以及這批物件的版本
//建立一個 item slice 進行遞迴計算他們的Object key
items:=make(map[string]interface{},len(list))for_,item:=rangelist{key,err:=c.keyFunc(item)iferr!=nil{returnKeyError{item,err}}items[key]=item}//委任給 cacheStorage 也就是 threadSafeStore 去做處理,threadSafeStore Replace 這裡的細節可以去上一章節複習。
//簡單來說就是使用 這一坨 Object 直接對 原有的進行取代
c.cacheStorage.Replace(items,resourceVersion)returnnil}
Resync
1
2
3
4
5
// Resync is meaningless for one of these
func(c*cache)Resync()error{//沒做事xD
returnnil}
上段 source code 中提到的 cache package 中的 NewIndexerInformer 是我們要關注的重點是一個重要的 function ,我們先來看看這個 function 裡面寫了什麼吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//傳入數值目前不是很重要,我們需要把重要放到 NewIndexer 來
//可以看到 NewIndexer 傳入了 DeletionHandlingMetaNamespaceKeyFunc 以及 cache package 中預設的 indexers。
//表示所有的物件都會透過 DeletionHandlingMetaNamespaceKeyFunc 來計算Object key 並且存放在 local cache 中。
funcNewIndexerInformer(lwListerWatcher,objTyperuntime.Object,resyncPeriodtime.Duration,hResourceEventHandler,indexersIndexers,)(Indexer,Controller){// This will hold the client state, as we know it.
clientState:=NewIndexer(DeletionHandlingMetaNamespaceKeyFunc,indexers)returnclientState,newInformer(lw,objType,resyncPeriod,h,clientState)}
我們再來看看其他用法,雖然這個方法在 Kubernetes 中非常少被用到但值得我們去了解。
1
2
3
4
5
6
7
8
9
10
11
12
13
//傳入數值目前不是很重要,我們需要把重要放到 NewStore 來
//一樣這邊傳入DeletionHandlingMetaNamespaceKeyFunc 來處理 Object Key 的計算
funcNewInformer(lwListerWatcher,objTyperuntime.Object,resyncPeriodtime.Duration,hResourceEventHandler,)(Store,Controller){// This will hold the client state, as we know it.
clientState:=NewStore(DeletionHandlingMetaNamespaceKeyFunc)returnclientState,newInformer(lw,objType,resyncPeriod,h,clientState)}
小結
大家可能比較不了解的地方在於 Object key 計算的方法,我在 Kubernetes source code 中挖掘了很久找到一個實作 keyFunc 的 function ,不確定還有沒有其他實作 keyFunc 的 function 。
// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace
funcMetaNamespaceIndexFunc(objinterface{})([]string,error){meta,err:=meta.Accessor(obj)iferr!=nil{return[]string{""},fmt.Errorf("object has no meta: %v",err)}return[]string{meta.GetNamespace()},nil}