之前了解了client-go中的架构设计,也就是 tools/cache
下面的一些概念,那么下面将对informer进行分析
Controller
在client-go informer架构中存在一个 controller
,这个不是 Kubernetes 中的Controller组件;而是在 tools/cache
中的一个概念,controller
位于 informer 之下,Reflector 之上。code
Config
从严格意义上来讲,controller
是作为一个 sharedInformer
使用,通过接受一个 Config
,而 Reflector
则作为 controller
的 slot。Config
则包含了这个 controller
里所有的设置。
|
|
controller
然后 controller
又为 reflertor
的上层
|
|
controller
中的方法,仅有一个 Run()
和 New()
;这意味着,controller
只是一个抽象的概念,作为 Reflector
, Delta FIFO
整合的工作流
而 controller
则是 SharedInformer
了。
Queue
这里的 queue
可以理解为是一个具有 Pop()
功能的 Indexer
;而 Pop()
的功能则是 controller
中的一部分;也就是说 queue
是一个扩展的 Store
, Store
是不具备弹出功能的。
|
|
而弹出的操作是通过 controller 中的 processLoop()
进行的,最终走到Delta FIFO中进行处理。
通过忙等待去读取要弹出的数据,然后在弹出前 通过PopProcessFunc
进行处理
|
|
|
|
Informer
通过对 Reflector
, Store
, Queue
, ListerWatcher
、ProcessFunc
, 等的概念,发现由 controller
所包装的起的功能并不能完成通过对API的动作监听,并通过动作来处理本地缓存的一个能力;这个情况下诞生了 informer
严格意义上来讲是 sharedInformer
|
|
newInformer是位于 tools/cache/controller.go 下,可以看出,这里面并没有informer的概念,这里通过注释可以看到,newInformer实际上是一个提供了存储和事件通知的informer。他关联的 queue
则是 Delta FIFO
,并包含了 ProcessFunc
, Store
等 controller的概念。最终对外的方法为 NewInformer()
|
|
可以看到 NewInformer()
就是一个带有 Store功能的controller,通过这些可以假定出,Informer 就是controller
,将queue中相关操作分发给不同事件处理的功能
SharedIndexInformer
shareInformer
为客户端提供了与apiserver一致的数据对象本地缓存,并支持多事件处理程序的informer,而 shareIndexInformer
则是对shareInformer
的扩展
|
|
SharedIndexInformer
是对SharedInformer的实现,可以从结构中看出,SharedIndexInformer
大致具有如下功能:
- 索引本地缓存
- controller,通过list watch拉取API并推入
Deltal FIFO
- 事件的处理
|
|
而在 tools/cache/share_informer.go 可以看到 shareIndexInformer 的运行过程
|
|
而在操作Delta FIFO中可以看到,做具体操作时,会将动作分发至对应的事件处理函数中,这个是informer初始化时对事件操作的函数
|
|
事件处理函数 processor
启动informer时也会启动注册进来的事件处理函数;processor
就是这个事件处理函数。
run()
函数会启动两个 listener,j监听事件处理业务函数 listener.run
和 事件的处理
|
|
可以看出,就是拿到的事件,根据注册的到informer的事件函数进行处理
|
|
informer中的事件的设计
了解了informer如何处理事件,就需要学习下,informer的事件系统设计 prossorListener
事件的添加
当在handleDelta时,会分发具体的事件
|
|
此时,事件泵 Pop()
会根据接收到的事件进行处理
|
|
该消息事件的流程图为
通过一个简单实例来学习client-go中的消息通知机制
|
|
总结,这里的机制类似于线程安全,进入临界区的一些算法,临界区就是 nextCh
,notification
就是保证了至少有一个进程可以进入临界区(要么分发事件,要么生产事件);nextCh
和 nextCh1
一个是局部管道一个是全局的,管道未初始化代表了死锁(阻塞);当有消息要处理时,会将局部管道 nextCh
赋值给 全局 nextCh1
此时相当于解除了分发的步骤(对管道赋值,触发分发操作);ringbuffer
实际上是提供了一个对 notification
加锁的操作,在没有处理的消息时,需要保障 notification
为空,同时也关闭了流程 nextCh
的写入。这里主要是考虑对golang中channel的用法