官术网_书友最值得收藏!

3.3.5 加載builtins

DockerDaemon設置完Trap特定信號的處理方法(即eng.shutdown()函數)之后,Docker Daemon實現了builtins的加載。Docker的builtins可以理解為:Docker Daemon運行過程中,注冊的一些任務(Job),這部分任務一般與容器的運行無關,與Docker Daemon的運行時信息有關。加載builtins的源碼實現如下:

if err := builtins.Register(eng); err != nil {
     log.Fatal(err)
}

加載builtins完成的具體工作是:向engine注冊多個Handler,以便后續在執行相應任務時,運行指定的Handler。這些Handler包括:Docker Daemon宿主機的網絡初始化、Web API服務、事件查詢、版本查看、Docker Registry的驗證與搜索等。源碼實現位于./docker/docker/builtins/builtins.go#L16-L30,如下:

func Register(eng *engine.Engine) error {
     if err := daemon(eng); err != nil {
          return err
     }
     if err := remote(eng); err != nil {
          return err
     }
     if err := events.New().Install(eng); err != nil {
          return err
     }
     if err := eng.Register("version", dockerVersion); err != nil {
          return err
     }
     return registry.NewService().Install(eng)
}

下面分析Register函數實現過程中最為主要的5個部分:daemon(eng)、remote(eng)、events.New().Install(eng)、eng.Register("version",dockerVersion)以及registry.NewService().Install(eng)。

1.注冊網絡初始化處理方法

daemon(eng)的實現過程,主要為eng對象注冊了一個鍵為"init_networkdriver"的處理方法,此處理方法的值為bridge.InitDriver函數,源碼如下:

func daemon(eng *engine.Engine) error {
     return eng.Register("init_networkdriver", bridge.InitDriver)
}

需要注意的是,向eng對象注冊處理方法,并不代表處理方法的值函數會被立即調用執行,如注冊init_networkdrive時bridge.InitDriver并不會直接運行,而是將bridge.InitDriver的函數入口作為init_networkdriver的值,寫入eng的handlers屬性中。當Docker Daemon接收到名為init_networkdriver的Job的執行請求時,bridge.InitDriver才被Docker Daemon調用執行。

Bridge.InitDriver的具體實現位于./docker/docker/daemon/networkdriver/bridge/driver.go#79-L175,主要作用為:

□ 獲取為Docker服務的網絡設備地址。

□ 創建指定IP地址的網橋。

□ 配置網絡iptables規則。

□ 另外還為eng對象注冊了多個Handler,如allocate_interface、release_interface、allocate_port以及link等。

本書將在第6章詳細分析Docker Daemon如何初始化宿主機的網絡環境。

2.注冊API服務處理方法

remote(eng)的實現過程,主要為eng對象注冊了兩個Handler,分別為serveapi與acceptconnections,源碼實現如下:

func remote(eng *engine.Engine) error {
     if err := eng.Register("serveapi", apiserver.ServeApi); err != nil {
          return err
     }
     return eng.Register("acceptconnections", apiserver.AcceptConnections)
}

注冊的兩個處理方法名稱分別為serveapi與acceptconnections,相應的執行方法分別為apiserver.ServeApi與apiserver.AcceptConnections,具體實現位于./docker/docker/api/server/server.go。其中,ServeApi執行時,通過循環多種指定協議,創建出goroutine協調來配置指定的http.Server,最終為不同協議的請求服務;而AcceptConnections的作用主要是:通知宿主機上init守護進程Docker Daemon已經啟動完畢,可以讓Docker Daemon開始服務API請求。

3.注冊events事件處理方法

events.New().Install(eng)的實現過程,為Docker注冊了多個event事件,功能是給Docker用戶提供API,使得用戶可以通過這些API查看Docker內部的events信息,log信息以及subscribers_count信息。具體的源碼位于./docker/docker/events/events.go#L29-L42,如下所示:

func (e *Events) Install(eng *engine.Engine) error {
     jobs := map[string]engine.Handler{
          "events":            e.Get,
          "log":               e.Log,
          "subscribers_count": e.SubscribersCount,
     }
     for name, job := range jobs {
          if err := eng.Register(name, job); err != nil {
               return err
          }
     }
     return nil
}

4.注冊版本處理方法

eng.Register("version",dockerVersion)的實現過程,向eng對象注冊key為version,value為dockerVersion執行方法的Handler。dockerVersion的執行過程中,會向名為version的Job的標準輸出中寫入Docker的版本、Docker API的版本、git版本、Go語言運行時版本,以及操作系統版本等信息。dockerVersion的源碼實現如下:

func dockerVersion(job *engine.Job) engine.Status {
     v := &engine.Env{}
     v.SetJson("Version", dockerversion.VERSION)
     v.SetJson("ApiVersion", api.APIVERSION)
     v.Set("GitCommit", dockerversion.GITCOMMIT)
     v.Set("GoVersion", runtime.Version())
     v.Set("Os", runtime.GOOS)
     v.Set("Arch", runtime.GOARCH)
     if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
          v.Set("KernelVersion", kernelVersion.String())
     }
     if _, err := v.WriteTo(job.Stdout); err != nil {
          return job.Error(err)
     }
     return engine.StatusOK
}

5.注冊registry處理方法

registry.NewService().Install(eng)的實現過程位于./docker/docker/registry/service.go,功能是:在eng對象對外暴露的API信息中添加docker registry的信息。若registry.NewService()被成功安裝,則會有兩個相應的處理方法注冊至eng,Docker Daemon通過Docker Client提供的認證信息向registry發起認證請求;search,在公有registry上搜索指定的鏡像,目前公有的registry只支持Docker Hub。

Install的具體實現如下:

func (s *Service) Install(eng *engine.Engine) error {
     eng.Register("auth", s.Auth)
     eng.Register("search", s.Search)
     return nil
}

至此,Docker Daemon所有builtins的加載全部完成,實現了向eng對象注冊特定的處理方法。

主站蜘蛛池模板: 芜湖县| 平乐县| 商丘市| 莱阳市| 清徐县| 图们市| 永靖县| 宜宾市| 玉树县| 八宿县| 应城市| 遵化市| 康乐县| 华池县| 定结县| 永兴县| 松原市| 双流县| 桦甸市| 嘉义市| 金沙县| 溧阳市| 正镶白旗| 古蔺县| 长葛市| 错那县| 奎屯市| 镇雄县| 临海市| 高州市| 达日县| 孙吴县| 阿拉善右旗| 平湖市| 临邑县| 讷河市| 聂荣县| 陵川县| 体育| 永登县| 普陀区|