【kubeedge源碼分析】edgecore源碼分析之一初始化啓動流程

 

 

     在 edgecore 啓動階段註冊模塊由 kubeedge/edge/cmd/app 包下的 registerModules 函數完成,註冊的模塊包括:

  • Edged:一個運行在 edge 節點的 agent 程序,管理邊緣的容器化應用程序
  • EdgeHub:邊緣的通信接口模塊。這是一個 Web 套接字客戶端,負責邊緣計算與雲服務的交互。包括同步雲端資源到邊緣端,以及報告邊緣端 host 和 device 狀態到雲端 
  • EdgeController:管理邊緣節點。它是一個擴展的 Kubernetes 控制器,管理邊緣節點和 pod 元數據,以便數據可以面向特定的邊緣節點
  • EventBus:使用 MQTT 處理內部邊緣通信。MQTT 客戶端與 MQTT 服務器(mosquitto)交互,爲其他組件提供發佈和訂閱功能
  • DeviceTwin:處理設備元數據的設備軟件鏡像。該模塊有助於處理設備狀態並將其同步到雲上。它還爲應用程序提供查詢接口,它連接到一個輕量級數據庫(SQLite)
  • MetaManager:管理邊緣節點上的元數據。這是 Edged 和 Edgehub 之間的消息處理器。負責在輕量級數據庫(SQLite)中存儲 / 檢索元數據
// registerModules register all the modules started in edgecore
func registerModules() {
   devicetwin.Register()
   edged.Register()
   edgehub.Register()
   eventbus.Register()
   edgemesh.Register()
   metamanager.Register()
   servicebus.Register()
   test.Register()
   dbm.InitDBManager()
}

 

1. main 函數

    一看挺熟悉的格式,kubernetes 代碼都是這麼搞的,使用了 cobra 框架

func main() {
	command := app.NewEdgeCoreCommand()
	logs.InitLogs()
	defer logs.FlushLogs()

	if err := command.Execute(); err != nil {
		os.Exit(1)
	}
}

   1.1 NewEdgeCoreCommand 函數

    registerModules 註冊模塊 (第 2 章節講解)

    Run 函數真正的運行階段,啓動各個模塊,以及設置優雅的終止程序 (第 3 章節講解)

// NewEdgeCoreCommand create edgecore cmd
func NewEdgeCoreCommand() *cobra.Command {
	opts := options.NewEdgeCoreOptions()
	cmd := &cobra.Command{
		Use: "edgecore",
		......
		Run: func(cmd *cobra.Command, args []string) {
			verflag.PrintAndExitIfRequested()
			flag.PrintFlags(cmd.Flags())

			// To help debugging, immediately log version
			klog.Infof("Version: %+v", version.Get())

			registerModules()
			// start all modules
			core.Run()
		},

 

2. registerModules 

    通過 registerModules 函數註冊相應的模塊,下面看看這些模塊怎麼註冊的

// registerModules register all the modules started in edgecore
func registerModules() {
	devicetwin.Register()
	edged.Register()
	edgehub.Register()
	eventbus.Register()
	edgemesh.Register()
	metamanager.Register()
	servicebus.Register()
	test.Register()
	dbm.InitDBManager()
}

   2.1 Register 函數

    路徑 github.com/kubeedge/beehive/pkg/core/module.go 引入了 beehive 包,使用全局 modules 和 disableModules 需要加載的與禁止的模塊,各個模塊需要所實現 Module 接口,需要實現下面的方法:

  • Name() string
  • Group() string
  • Start()
  • Cleanup()
var (
	// Modules map
	modules         map[string]Module
	disabledModules map[string]Module
)

func init() {
	modules = make(map[string]Module)
	disabledModules = make(map[string]Module)
	config.AddConfigChangeCallback(moduleChangeCallback{})
	eventListener := config.EventListener{Name: "eventListener1"}
	config.CONFIG.RegisterListener(eventListener, "modules.enabled")
}

   看看其中一個模塊的實現,devicetwin.go,路徑 kubeege/edge/pkg/devicetwin/devicetwin.go

   2.2 devicetwin

     簡單明瞭,調用 beehive 的 Register 函數註冊模塊

//DeviceTwin the module
type DeviceTwin struct {
	HeartBeatToModule map[string]chan interface{}
	DTContexts        *dtcontext.DTContext
	DTModules         map[string]dtmodule.DTModule
	cancel            context.CancelFunc
}

// Register register devicetwin
func Register() {
	dtclient.InitDBTable()
	dt := DeviceTwin{}
	core.Register(&dt)
}

     2.2.1 DeviceTwin 方法 Name 和 Group

    可以得到 DeviceTwin 模塊的 name 爲 twin,group 爲 twin

//Name get name of the module
func (dt *DeviceTwin) Name() string {
	return "twin"
}

//Group get group of the module
func (dt *DeviceTwin) Group() string {
	return modules.TwinGroup
}

     2.2.2 DeviceTwin 方法 Start 

     deviceTwin 模塊和輕量級數據庫 sqlite 交互,SyncDeviceFromSqlite 函數從數據庫同步數據,應該有表 device,device_attr,device_twin

//Start run the module
func (dt *DeviceTwin) Start() {
	var ctx context.Context
	dtContexts, _ := dtcontext.InitDTContext()
	dt.HeartBeatToModule = make(map[string]chan interface{})
	dt.DTModules = make(map[string]dtmodule.DTModule)
	dt.DTContexts = dtContexts
	ctx, dt.cancel = context.WithCancel(context.Background())
	err := SyncSqlite(dt.DTContexts)
	if err != nil {
		klog.Errorf("Start DeviceTwin Failed, Sync Sqlite error:%v", err)
		return
	}
	dt.runDeviceTwin(ctx)
}

 

3. StartModules 函數

// StartModules starts modules that are registered
func StartModules() {
	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)

	modules := GetModules()
	for name, module := range modules {
		//Init the module
		beehiveContext.AddModule(name)
		//Assemble typeChannels for sendToGroup
		beehiveContext.AddModuleGroup(name, module.Group())
		go module.Start()
		klog.Infof("Starting module %v", name)
	}
}

   3.1 InitContext 函數

    beehive 採用 golang 的 channel 方式實現模塊間通訊,未來可能有 unix socke t的通訊方式。kubernetes CSI 等模塊間使用的時 socket 通訊方式,初始化全局上下文 context,context 包含兩個對象 moduleContext,messageContext

// Context is global context object
type Context struct {
   moduleContext  ModuleContext
   messageContext MessageContext
}
// InitContext gets global context instance
func InitContext(contextType string) {
	once.Do(func() {
		context = &Context{}
		switch contextType {
		case MsgCtxTypeChannel:
			channelContext := NewChannelContext()
			context.messageContext = channelContext
			context.moduleContext = channelContext
		default:
			klog.Fatalf("Do not support context type:%s", contextType)
		}
	})
}

     3.1.1 moduleContext 模塊管理

  • AddModule爲模塊創建默認 buffer 大小爲 1024 的channel,channels成員中將模塊名字映射到該 channel,用於“單播” 
  • AddModuleGroup 將一個模塊對應的 channel 添加到所屬 group,也就是將 ChannelContext 的 typeChannels[group][module]設置爲模塊對應channel,用於“組播”
//constants for channel context
const (
   ChannelSizeDefault = 1024

   MessageTimeoutDefault = 30 * time.Second

   TickerTimeoutDefault = 20 * time.Millisecond
)

     3.1.1.1 結構體 ChannelContext

     channel channels,typeChannels,anonChannels,定義的組如下:

const (
   // BusGroup group
   BusGroup = "bus"
   // HubGroup group
   HubGroup = "hub"
   // TwinGroup group
   TwinGroup = "twin"
   // MetaGroup group
   MetaGroup = "meta"
   //EdgedGroup group
   EdgedGroup = "edged"
   // UserGroup is ServiceBus group
   UserGroup = "user"
   // MeshGroup group
   MeshGroup = "mesh"
)
// ChannelContext is object for Context channel
type ChannelContext struct {
	//ConfigFactory goarchaius.ConfigurationFactory
	channels     map[string]chan model.Message
	chsLock      sync.RWMutex
	typeChannels map[string]map[string]chan model.Message
	typeChsLock  sync.RWMutex
	anonChannels map[string]chan model.Message
	anonChsLock  sync.RWMutex
}

 

//ModuleContext is interface for context module management
type ModuleContext interface {
	AddModule(module string)
	AddModuleGroup(module, group string)
	Cleanup(module string)
}

     3.1.2 messageContext 消息同步

     實現了模塊間消息的同步與異步發送

//MessageContext is interface for message syncing
type MessageContext interface {
	// async mode
	Send(module string, message model.Message)
	Receive(module string) (model.Message, error)
	// sync mode
	SendSync(module string, message model.Message, timeout time.Duration) (model.Message, error)
	SendResp(message model.Message)
	// group broadcast
	SendToGroup(moduleType string, message model.Message)
	SendToGroupSync(moduleType string, message model.Message, timeout time.Duration) error
}

 

edgecore 啓動流程總結:

  •     調用  registerModules 函數主冊各個模塊
  •     啓動各個模塊調用 StartModules函數創建模塊間通訊機制,並啓動協程調用每個模塊的Start函數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章