kubeedge源碼分析系列之edgecore(一)

kubeedge源碼分析系列之edgecore(一)

本系列的源碼分析是在 commit da92692baa660359bb314d89dfa3a80bffb1d26c 之上進行的。git

cloudcore部分的源碼分析是在kubeedge源碼分析系列之總體架構基礎上展開的,若是沒有閱讀過kubeedge源碼分析系列之總體架構,直接閱讀本文,會感受比較突兀。github

本文概述

本文對edgecore進行了展開,由於edgecore中的功能組件比較多,共包括devicetwin、edged、edgehub、eventbus、edgemesh、metamanager、servicebus、和test共8個功能模塊,限於篇幅,須要多篇文章才能分析清楚,本文只對devicetwin進行剖析,具體以下:golang

  1. devicetwin的struct調用鏈剖析
  2. devicetwin的具體邏輯剖析
  3. devicetwin的緩存機制剖析

devicetwin的struct調用鏈剖析

從edgecore模塊註冊函數入手:sql

kubeedge/edge/cmd/edgecore/app/server.go數據庫

// registerModules register all the modules started in edgecore
func registerModules() {
	devicetwin.Register()
	...
}
複製代碼

進入registerModules()函數中的devicetwin.Register(),具體以下:緩存

kubeedge/edge/pkg/devicetwin/devicetwin.go微信

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

在Register()函數中,主要作了以下3件事:架構

  1. 初始化devicetwin須要的數據庫表(dtclient.InitDBTable());
  2. 實例化DeviceTwin struct(dt := DeviceTwin{});
  3. 註冊將已經實例化的DeviceTwin struct(core.Register(&dt));

下面要深刻剖析初始化devicetwin須要的數據庫表具體作了哪些事情,DeviceTwin struct具體有哪些屬性組成的。併發

devicetwin數據庫相關struct剖析

這部分剖析初始化devicetwin須要的數據庫及數據庫表相關的struct。app

kubeedge/edge/pkg/devicetwin/dtclient/sql.go

//InitDBTable create table
func InitDBTable() {
	klog.Info("Begin to register twin model")
	dbm.RegisterModel("twin", new(Device))
	dbm.RegisterModel("twin", new(DeviceAttr))
	dbm.RegisterModel("twin", new(DeviceTwin))
}	
複製代碼

在InitDBTable()函數中,經過封裝的beego的orm建立了數據庫"twin",並初始化了"device"、"device_attr"和"device_twin"3張表,與上述三張表對應的結構體以下:

kubeedge/edge/pkg/devicetwin/dtclient/device_db.go

//Device the struct of device
type Device struct {
	ID          string `orm:"column(id); size(64); pk"`
	Name        string `orm:"column(name); null; type(text)"`
	Description string `orm:"column(description); null; type(text)"`
	State       string `orm:"column(state); null; type(text)"`
	LastOnline  string `orm:"column(last_online); null; type(text)"`
}
複製代碼

kubeedge/edge/pkg/devicetwin/dtclient/deviceattr_db.go

//DeviceAttr the struct of device attributes
type DeviceAttr struct {
	ID          int64  `orm:"column(id);size(64);auto;pk"`
	DeviceID    string `orm:"column(deviceid); null; type(text)"`
	Name        string `orm:"column(name);null;type(text)"`
	Description string `orm:"column(description);null;type(text)"`
	Value       string `orm:"column(value);null;type(text)"`
	Optional    bool   `orm:"column(optional);null;type(integer)"`
	AttrType    string `orm:"column(attr_type);null;type(text)"`
	Metadata    string `orm:"column(metadata);null;type(text)"`
}
複製代碼

kubeedge/edge/pkg/devicetwin/dtclient/devicetwin_db.go

//DeviceTwin the struct of device twin
type DeviceTwin struct {
	ID              int64  `orm:"column(id);size(64);auto;pk"`
	DeviceID        string `orm:"column(deviceid); null; type(text)"`
	Name            string `orm:"column(name);null;type(text)"`
	Description     string `orm:"column(description);null;type(text)"`
	Expected        string `orm:"column(expected);null;type(text)"`
	Actual          string `orm:"column(actual);null;type(text)"`
	ExpectedMeta    string `orm:"column(expected_meta);null;type(text)"`
	ActualMeta      string `orm:"column(actual_meta);null;type(text)"`
	ExpectedVersion string `orm:"column(expected_version);null;type(text)"`
	ActualVersion   string `orm:"column(actual_version);null;type(text)"`
	Optional        bool   `orm:"column(optional);null;type(integer)"`
	AttrType        string `orm:"column(attr_type);null;type(text)"`
	Metadata        string `orm:"column(metadata);null;type(text)"`
}
複製代碼

在以上3個文件中除了與"device"、"device_attr"和"device_twin"3張表對應的struct定義外,還有針對這三張表的增、刪、改、查方法的定義,感興趣的同窗能夠在本文剖析的基礎上去本身嘗試剖析。

DeviceTwin struct組成剖析

該部分對DeviceTwin struct的組成進行剖析。接着「devicetwin的struct調用鏈剖析」的 2. 實例化DeviceTwin struct(dt := DeviceTwin{})往下剖析,進入DeviceTwin struct的定義:

kubeedge/edge/pkg/devicetwin/devicetwin.go

//DeviceTwin the module
type DeviceTwin struct {
	context      *context.Context
	dtcontroller *DTController
}
複製代碼

DeviceTwin struct的定義由 *context.Context 和 *DTController兩部分組成,其中*context.Context能夠參考kubeedge源碼分析系列之cloudcore的「cloudcore功能模塊之間通訊的消息框架」,這裏就再也不贅述。下面重點剖析DTController,進入DTController的定義:

kubeedge/edge/pkg/devicetwin/dtcontroller.go

//DTController controller for devicetwin
type DTController struct {
	HeartBeatToModule map[string]chan interface{}
	DTContexts        *dtcontext.DTContext
	DTModules         map[string]dtmodule.DTModule
	Stop              chan bool
}
複製代碼

在DTController struct定義中發現*dtcontext.DTContext和dtmodule.DTModule還不清楚,繼續進入它們的定義:

kubeedge/edge/pkg/devicetwin/dtcontext/dtcontext.go

//DTContext context for devicetwin
type DTContext struct {
	GroupID        string
	NodeID         string
	CommChan       map[string]chan interface{}
	ConfirmChan    chan interface{}
	ConfirmMap     *sync.Map
	ModulesHealth  *sync.Map
	ModulesContext *context.Context
	DeviceList     *sync.Map
	DeviceMutex    *sync.Map
	Mutex          *sync.RWMutex
	// DBConn *dtclient.Conn
	State string
}
複製代碼

從DTContext struct的定義能夠看出DTContext struct主要用來實現devicetwin的通訊和緩存。

kubeedge/edge/pkg/devicetwin/dtmodule/dtmodule.go

//DTModule module for devicetwin
type DTModule struct {
	Name   string
	Worker dtmanager.DTWorker
}
複製代碼

在 DTModule struct定義中dtmanager.DTWorker是interface type,其定義以下:

kubeedge/edge/pkg/devicetwin/dtmanager/dtworker.go

//DTWorker worker for devicetwin
type DTWorker interface {
	Start()
}
複製代碼

從dtmanager.DTWorker這個interface type能夠推測DTModule有多種類型,並且都實現了DTWorker interface,在kubeedge/edge/pkg/devicetwin/dtmodule/dtmodule.go中的InitWorker(...)就是來實例化DTModule的多種類型的,具體定義以下:

kubeedge/edge/pkg/devicetwin/dtmodule/dtmodule.go

// InitWorker init worker
func (dm *DTModule) InitWorker(recv chan interface{}, confirm chan interface{}, heartBeat chan interface{}, dtContext *dtcontext.DTContext) {
	switch dm.Name {
	case dtcommon.MemModule:
		dm.Worker = dtmanager.MemWorker{
			Group: dtcommon.MemModule,
			Worker: dtmanager.Worker{
				ReceiverChan:  recv,
				ConfirmChan:   confirm,
				HeartBeatChan: heartBeat,
				DTContexts:    dtContext,
		},
	}

	...
}
複製代碼

從InitWorker(...)函數的定義中能夠梳理出DTModule有MemWorker、TwinWorker、DeviceWorker和CommWorker四種類型,至於每種類型有哪些屬性,用來作什麼的,感興趣的同窗能夠在本文梳理的基礎上本身嘗試剖析。

到此edgecore中devicetwin的struct調用鏈剖析就所有結束了,有分析的不夠深刻或沒有覆蓋到的,感興趣的同窗能夠在本文的基礎上自行剖析,也能夠在評論區裏留言。

devicetwin的具體邏輯剖析

從devicetwin的啓動函數入手:

kubeedge/edge/pkg/devicetwin/devicetwin.go

//Start run the module
func (dt *DeviceTwin) Start(c *context.Context) {
	controller, err := InitDTController(c)
	if err != nil {
		klog.Errorf("Start device twin failed, due to %v", err)
	}
	dt.dtcontroller = controller
	dt.context = c
	err = controller.Start()
	if err != nil {
		klog.Errorf("Start device twin failed, due to %v", err)
	}
}
複製代碼

在啓動函數中主要作了以下幾件事情:

  1. 初始化DTController(controller, err := InitDTController(c));
  2. 啓動已經初始化的DTController(err = controller.Start());

初始化DTController時把傳入的beehive context消息框架實例,並在其中初始化一些devicetwin所需的channel,用來與傳入的beehive context消息框架實例進行交互,本文就不展開剖析了,感興趣的同窗能夠在本文梳理的基礎上本身嘗試剖析。

下面深刻剖析已經初始化的DTController在啓動過程當中和啓動之後所作的事,進入DTController啓動函數Start()的定義:

kubeedge/edge/pkg/devicetwin/dtcontroller.go

//Start devicetwin controller
func (dtc *DTController) Start() error {
	err := SyncSqlite(dtc.DTContexts)
	...
	moduleNames := []string{dtcommon.MemModule, dtcommon.TwinModule, 	dtcommon.DeviceModule, dtcommon.CommModule}
	for _, v := range moduleNames {
		dtc.RegisterDTModule(v)
		go dtc.DTModules[v].Start()
	}
	...
	}
}
複製代碼

在上面的定義中主要作了2件事:

  1. 將數據庫中的內容加載到內存中來(err := SyncSqlite(dtc.DTContexts));

  2. 啓動devicetwin中全部的module:

    moduleNames := []string{dtcommon.MemModule, dtcommon.TwinModule, 	dtcommon.DeviceModule, dtcommon.CommModule}
     for _, v := range moduleNames {
     	dtc.RegisterDTModule(v)
     	go dtc.DTModules[v].Start()
     }
    複製代碼

到此edgecore中devicetwin的具體邏輯剖析就所有結束了,有分析的不夠深刻或沒有覆蓋到的,感興趣的同窗能夠在本文的基礎上自行剖析,也能夠在評論區裏留言。

devicetwin的緩存機制剖析

devicetwin中緩存是利用golang自己的sync.Map來實現的,這裏就不展開剖析了。若是真是這樣的話,推測kubeedge在edge端的offline mode也是基於golang自己的sync.Map來實現的,這樣就會帶來一下問題:

  1. 用golang自己的sync.Map須要到處用鎖,這個在併發量大的狀況下會出現堵塞;
  2. 用golang自己的sync.Map,其在內存裏最大限度能緩存多少數據,緩存週期怎麼控制,緩存與持久存儲怎麼平衡;

到此「kubeedge源碼分析系列之edgecore(一)」就所有結束了,有分析的不夠深刻或沒有覆蓋到的,感興趣的同窗能夠在本文的基礎上自行剖析,也能夠在評論區裏留言。

本文是「之江實驗室端邊雲操做系統團隊」 kubeedge源碼分析系列的第三篇,接下來會對各組件的源碼進行系統分析。若是有機會咱們團隊也會積極解決kubeedge的issue和實現新的feature。

這是咱們「之江實驗室端邊雲操做系統團隊」維護的「之江實驗室kubeedge源碼分析羣「微信羣,歡迎你們的參與!!!

之江實驗室kubeedge源碼分析羣二維碼入口
相關文章
相關標籤/搜索