client-go源碼分析(3):Indexer, cache, threadSafeMap

前言

本文聚焦client-go v11.0.0 controller框架Indexer對象,分析源碼indexer的實現(xiàn)。關(guān)于client-go的介紹已有優(yōu)秀文章,可參考第一篇參考文檔,本文不再贅述。

1 cache - indexer對象關(guān)系

golang的struct和interface之間是弱耦合關(guān)系,即struct只需要實現(xiàn)了某個interface的所有方法,就認為該struct實現(xiàn)了該interface。cache和Store對象關(guān)系如下:

cache UML組件圖

從類的實現(xiàn)、組合關(guān)系上可見,cache實現(xiàn)了Store interface和Index interface的所有方法,因此cache可以賦值給Store和Index接口。理解threadSafeMap的實現(xiàn)能幫助我們理解cache。

2 理解threadSafeMap的實現(xiàn)

幾個內(nèi)部索引對象及其關(guān)系

type IndexFunc func(obj interface) ([]string, error)

type Indexers map[string]indexFunc

type Index map[string]sets.String

type indices map[string]Index

從上述幾個對象的命名和關(guān)系看,很難理解幾個對象的依賴關(guān)系。我們首先梳理幾個對象之間的關(guān)系,其次分析一個pod對象的增、刪、改時,幾個索引對象的狀態(tài)遷移如何發(fā)生。

2.1 threadSafeMap內(nèi)部對象關(guān)系

threadSafeMap內(nèi)部對象關(guān)系示意圖

Items:

Items類型map[string] interface{},用來存儲runtime.object,map的key(對象鍵)用函數(shù)MetaNamespaceKeyFunc生成,value是runtime.object本身。

Indexers:

indexers類型是map[string]indexFunc,用來存儲indexFunc(索引鍵計算函數(shù)),map的key是indexFuncName,value是indexFunc。注意兩個要點:1. 區(qū)別對象鍵和索引鍵;2. {indexName: indexFunc}是外部調(diào)用者傳入,調(diào)用關(guān)系參考k8s源碼: kubernetes-master\pkg\client\informers\informers_generated\internalversion\extensions\internalversion\deployment.go:

cache.MetaNamespaceIndexFunc函數(shù)調(diào)用

cache.MetaNamespaceIndexFunc函數(shù)注釋:

// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace.

Indices:

Indices類型map[string]Index。indices是對象快速索引表,map的key是indexName,value是Index對象,即map[string]sets.String。

Index:

Index類型map[string]sets.String。Index map的key是indexFunc計算的值,如MetaNamespaceIndexFunc返回的是namespace,如果使用indexByPodNodeName(源碼:kubernetes-master\pkg\controller\daemon\daemon_controller.go)那么返回nodename。

indexSet:

IndexSet是筆者自己取的名字。IndexSet是set.String類型,值是對象鍵objkey。

到此為止,相信細心的讀者可能會發(fā)現(xiàn),threadSafeMap做了兩件事:

1)存儲:保存k8s runtime.object到items map。

2)索引:為items map的每個對象建立三層索引:第一層是indices map的類別索引,如按'namespace', 'nodeName'索引;第二層是index map的詳細類別索引,如'namespace1','namespace2'… 或者'nodeName1','nodeName2'……;第三層是indexSet的對象鍵。第三層索引才真正索引到runtime.object。

2.2 threadSafeMap關(guān)鍵實現(xiàn)分析

以兩個典型的方法func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string)和func (c *threadSafeMap) deleteFromIndices(obj interface{}, key string)為例分析threadSafeMap內(nèi)部對象的狀態(tài)遷移過程。

deleteFromIndices實現(xiàn)

deleteFromIndices被Delete,updateIndices等函數(shù)調(diào)用,它的功能是刪除indices的某個索引。deleteFromIndices函數(shù)執(zhí)行步驟如下:

1)遍歷indexFunc map c.indexers獲取第一層索引indices的類別name,并計算第二層索引index的詳細索引類別indexValue;

2)遍歷第二層索引表index,依次刪除第三層索引表indexSet的對象鍵。

updateIndices實現(xiàn)

updateIndices函數(shù)被Add,Update,Replace等函數(shù)調(diào)用。updateIndices執(zhí)行步驟如下:

1)updateIndices函數(shù)首先刪除oldObj的索引鍵;

2)遍歷indexFunc map c.indexers,獲取第一層索引indices的索引類別name,并計算第二層索引Index的詳細索引類別indexValues(數(shù)組);

3)遍歷第二層索引Index,依次執(zhí)行:若第三層索引IndexSet為空則添加一個空set;若非空則添加對象鍵到第三層索引IndexSet。

3 結(jié)語

到此為止threadSafeMap的機制基本分析清楚,cache無非threadSafeMap的封裝和擴展,核心機制是一樣的,就不再細說 。

4 參考文檔

http://www.itdecent.cn/p/d17f70369c35

https://blog.csdn.net/weixin_42663840/article/details/81530606

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容