這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
manager.localserver是建立的本地Unix socket,用來等待處理swarmctl發來的命令請求(源碼在manager/controlapi目錄)。Manager.Run()函數裡localserver相關代碼如下:
baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode, m.config.SecurityConfig.RootCA())......proxyOpts := []grpc.DialOption{ grpc.WithBackoffMaxDelay(time.Second), grpc.WithTransportCredentials(m.config.SecurityConfig.ClientTLSCreds),}cs := raftpicker.NewConnSelector(m.RaftNode, proxyOpts...)m.connSelector = cs......// localProxyControlAPI is a special kind of proxy. It is only wired up// to receive requests from a trusted local socket, and these requests// don't use TLS, therefore the requests it handles locally should// bypass authorization. When it proxies, it sends them as requests from// this manager rather than forwarded requests (it has no TLS// information to put in the metadata map).forwardAsOwnRequest := func(ctx context.Context) (context.Context, error) { return ctx, nil }localProxyControlAPI := api.NewRaftProxyControlServer(baseControlAPI, cs, m.RaftNode, forwardAsOwnRequest)......api.RegisterControlServer(m.localserver, localProxyControlAPI)
(1)首先看一下controlapi.Server和controlapi.NewServer()的定義:
// Server is the Cluster API gRPC server.type Server struct { store *store.MemoryStore raft *raft.Node rootCA *ca.RootCA}// NewServer creates a Cluster API server.func NewServer(store *store.MemoryStore, raft *raft.Node, rootCA *ca.RootCA) *Server { return &Server{ store: store, raft: raft, rootCA: rootCA, }}
controlapi.NewServer()函數就是用來建立一個響應swarmctl程式發出的control命令請求的server。
其中store.MemoryStore是一個很重要的結構體:
// MemoryStore is a concurrency-safe, in-memory implementation of the Store// interface.type MemoryStore struct { // updateLock must be held during an update transaction. updateLock sync.Mutex memDB *memdb.MemDB queue *watch.Queue proposer state.Proposer}
而watch.Queue定義如下:
// Queue is the structure used to publish events and watch for them.type Queue struct { broadcast *events.Broadcaster}......// Watch returns a channel which will receive all items published to the// queue from this point, until cancel is called.func (q *Queue) Watch() (eventq chan events.Event, cancel func()) { return q.CallbackWatch(nil)}......// Publish adds an item to the queue.func (q *Queue) Publish(item events.Event) { q.broadcast.Write(item)}
簡單地講,就是當Server.store發生變化時,把資料更新到memDB的同時,也要發送訊息到queue裡,這樣manager監聽在相應channel的goroutine就可以收到並處理請求。
下面代碼就是把當前cluster的資訊填充到新建立的controlapi.Server變數裡:
baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode, m.config.SecurityConfig.RootCA())
(2)
proxyOpts := []grpc.DialOption{ grpc.WithBackoffMaxDelay(time.Second), grpc.WithTransportCredentials(m.config.SecurityConfig.ClientTLSCreds),}cs := raftpicker.NewConnSelector(m.RaftNode, proxyOpts...)m.connSelector = cs......// localProxyControlAPI is a special kind of proxy. It is only wired up// to receive requests from a trusted local socket, and these requests// don't use TLS, therefore the requests it handles locally should// bypass authorization. When it proxies, it sends them as requests from// this manager rather than forwarded requests (it has no TLS// information to put in the metadata map).forwardAsOwnRequest := func(ctx context.Context) (context.Context, error) { return ctx, nil }localProxyControlAPI := api.NewRaftProxyControlServer(baseControlAPI, cs, m.RaftNode, forwardAsOwnRequest)
上述代碼建立出一個raftProxyControlServer類型的變數:
type raftProxyControlServer struct { local ControlServer connSelector *raftpicker.ConnSelector cluster raftpicker.RaftCluster ctxMods []func(context.Context) (context.Context, error)}
localProxyControlAPI含義是如果收到swarmctl請求的manager是leader(swarmctl和manager當然位於同一台機器上),則會處理請求,否則就轉寄給這個cluster的leader。
(3)
api.RegisterControlServer(m.localserver, localProxyControlAPI)
上述代碼則是把localserver所對應的Unix socket和raftProxyControlServer關聯起來。