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
}