這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Docker Swarm manage函數的最後部分是建立Docker API server部分:
server := api.NewServer(hosts, tlsConfig)if c.Bool("replication") { ...... setupReplication(c, cl, server, discovery, addr, leaderTTL, tlsConfig)} else { server.SetHandler(api.NewPrimary(cl, tlsConfig, &statusHandler{cl, nil, nil}, c.GlobalBool("debug"), c.Bool("cors"))) cluster.NewWatchdog(cl)}log.Fatal(server.ListenAndServe())
Server結構體定義在api/server.go:
type Server struct { hosts []string tlsConfig *tls.Config dispatcher *dispatcher}
它的核心方法是ListenAndServe(),即為每個host起一個goroutine監聽並處理Docker client的串連請求。
func (s *Server) ListenAndServe() error { chErrors := make(chan error, len(s.hosts)) for _, host := range s.hosts { protoAddrParts := strings.SplitN(host, "://", 2) if len(protoAddrParts) == 1 { protoAddrParts = append([]string{"tcp"}, protoAddrParts...) } go func() { log.WithFields(log.Fields{"proto": protoAddrParts[0], "addr": protoAddrParts[1]}).Info("Listening for HTTP") var ( l net.Listener err error server = &http.Server{ Addr: protoAddrParts[1], Handler: s.dispatcher, } ) switch protoAddrParts[0] { case "unix": l, err = newUnixListener(protoAddrParts[1], s.tlsConfig) case "tcp": l, err = newListener("tcp", protoAddrParts[1], s.tlsConfig) default: err = fmt.Errorf("unsupported protocol: %q", protoAddrParts[0]) } if err != nil { chErrors <- err } else { chErrors <- server.Serve(l) } }() } for i := 0; i < len(s.hosts); i++ { err := <-chErrors if err != nil { return err } } return nil}