本系列的源碼分析是在 commit da92692baa660359bb314d89dfa3a80bffb1d26c 之上進行的。git
cloudcore部分的源碼分析是在kubeedge源碼分析系列之總體架構基礎上展開的,若是沒有閱讀過kubeedge源碼分析系列之總體架構,直接閱讀本文,會感受比較突兀。github
本文對edgecore進行了展開,由於edgecore中的功能組件比較多,共包括devicetwin、edged、edgehub、eventbus、edgemesh、metamanager、servicebus、和test共8個功能模塊,限於篇幅,須要多篇文章才能分析清楚,本文只對devicetwin進行剖析,具體以下:golang
從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件事:架構
下面要深刻剖析初始化devicetwin須要的數據庫表具體作了哪些事情,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調用鏈剖析」的 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的啓動函數入手:
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)
}
}
複製代碼
在啓動函數中主要作了以下幾件事情:
初始化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件事:
將數據庫中的內容加載到內存中來(err := SyncSqlite(dtc.DTContexts));
啓動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中緩存是利用golang自己的sync.Map來實現的,這裏就不展開剖析了。若是真是這樣的話,推測kubeedge在edge端的offline mode也是基於golang自己的sync.Map來實現的,這樣就會帶來一下問題:
到此「kubeedge源碼分析系列之edgecore(一)」就所有結束了,有分析的不夠深刻或沒有覆蓋到的,感興趣的同窗能夠在本文的基礎上自行剖析,也能夠在評論區裏留言。
本文是「之江實驗室端邊雲操做系統團隊」 kubeedge源碼分析系列的第三篇,接下來會對各組件的源碼進行系統分析。若是有機會咱們團隊也會積極解決kubeedge的issue和實現新的feature。
這是咱們「之江實驗室端邊雲操做系統團隊」維護的「之江實驗室kubeedge源碼分析羣「微信羣,歡迎你們的參與!!!