之前了解了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的用法

