This is a creation in Article, where the information may have evolved or changed.
Manager
session
the processing request is through _Dispatcher_Session_Handler
this function ( ./api/dispatcher.pb.go
):
func _Dispatcher_Session_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(SessionRequest) if err := stream.RecvMsg(m); err != nil { return err } return srv.(DispatcherServer).Session(m, &dispatcherSessionServer{stream})}
The actual function call stack is as follows:
0 0X0000000000B65CBF in Github.com/docker/swarmkit/manager/dispatcher. (*dispatcher). Session at/go/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go:7681 0x0000000000782aa5 in Github.com/docker/swarmkit/api. (*authenticatedwrapperdispatcherserver). Session at/go/src/github.com/docker/swarmkit/api/dispatcher.pb.go:2072 0x000000000078e505 in github.com/docker/ Swarmkit/api. (*raftproxydispatcherserver). Session at/go/src/github.com/docker/swarmkit/api/dispatcher.pb.go:11213 0x0000000000789c2a in github.com/docker/ Swarmkit/api._dispatcher_session_handler at/go/src/github.com/docker/swarmkit/api/dispatcher.pb.go:6674 0x0000000000909646 in Github.com/docker/swarmkit/vendor/google.golang.org/grpc. (*server). Processstreamingrpc at/go/src/github.com/docker/swarmkit/vendor/google.golang.org/grpc/server.go:6025 0x000000000090b002 in Github.com/docker/swarmkit/vendor/google.golang.org/grpc. (*server). Handlestream At/go/src/github.com/docker/swarmkit/vendor/google.golang.org/grpc/server.go:6866 0X000000000090FCBE in Github.com/docker/swarmkit/vendor/google.golang.org/grpc. (*server). servestreams.func1.1 at/go/src/github.com/docker/swarmkit/vendor/google.golang.org/grpc/server.go : 3487 0x0000000000462bf0 in Runtime.goexit at/usr/local/go/src/runtime/asm_amd64.s:1998
The
dispatcher.session ()
function code is as follows:
Session is a stream which controls agent connection.//each message contains list of the backup Managers with weights. Also there is//a special boolean field Disconnect which if true indicates that node should//reconnect to another Manager Immediately.func (d *dispatcher) Session (R *api. Sessionrequest, Stream API. Dispatcher_sessionserver) Error {ctx: = stream. Context () NodeInfo, err: = ca. Remotenode (CTX) if err! = Nil {return err} NodeID: = Nodeinfo.nodeid If err: = d.isrunninglocked (); Err! = Nil {return err}//Register the node. SessionID, err: = D.register (stream. Context (), NodeID, r.description) if err! = Nil {return err} fields: = Logrus. fields{"Node.id": NodeID, "node.session": SessionID, "Method": "(*dispatcher). Session ",} if Nodeinfo.forwardedby! = nil {fields[" forwarder.id "] = NodeInfo.ForwardedBy.NodeID} log : = log. G (CTX). Withfields (Fields) var nodeObj *Api. Node nodeupdates, Cancel, err: = store. Viewandwatch (D.store, func (READTX store). READTX) Error {NODEOBJ = store. GetNode (READTX, NodeID) return nil}, state. Eventupdatenode{node: &api. Node{id:nodeid}, Checks: []state. Nodecheckfunc{state. Nodecheckid}},) if Cancel! = Nil {defer cancel ()} If err! = Nil {log. Witherror (ERR). Error ("Viewandwatch Node failed")} if _, err = D.nodes.getwithsession (NodeID, SessionID); Err! = Nil {return err} if err: = stream. Send (&api. sessionmessage{Sessionid:sessionid, Node:nodeobj, Managers: D.getmanagers (), Networkbootstrapkeys:d.networkbootstrapkeys,}); Err! = Nil {return err} managerupdates, Mgrcancel: = D.mgrqueue.watch () defer mgrcancel () Keymgrupdat ES, Keymgrcancel: = D.keymgrqueue.watch () defer keymgrcancel ()//Disconnectnode is a helper forcibly shutdown Conne CtioN Disconnectnode: = func () error {//force disconnect by shutting the stream. Transportstream, OK: = transport. Streamfromcontext (stream. Context ()) If OK {//If we have the transport stream and we can signal a disconnect//in the C Lient. If err: = Transportstream.servertransport (). Close (); Err! = Nil {log. Witherror (ERR). Error ("Session End")}} Nodestatus: = API. Nodestatus{state:api. nodestatus_disconnected, Message: "Node is currently trying to find new manager"} If Err: = D.noderemove (NodeID, no Destatus); Err! = Nil {log. Witherror (ERR). Error ("Failed to remove node")}//Still return a abort if the transport closure was ineffective. Return GRPC. Errorf (codes. Aborted, "node must disconnect")} for {//after each message send, we need to check the nodes SessionID have N ' t//changed. If it has, we'll the stream and make the NOde//Re-register. node, err: = D.nodes.getwithsession (NodeID, SessionID) if err! = Nil {return err} var mg RS []*api. Weightedpeer var disconnect bool Select {case EV: = <-managerupdates:mgrs = ev. ( []*api. Weightedpeer) Case EV: = <-nodeupdates:nodeobj = ev. (state. Eventupdatenode). Node case <-stream. Context (). Done (): return stream. Context (). ERR () Case <-node. Disconnect:disconnect = True Case <-d.ctx.done (): Disconnect = True Case <-keym Grupdates:} if Mgrs = = Nil {Mgrs = D.getmanagers ()} If err: = stream. Send (&api. sessionmessage{Sessionid:sessionid, Node:nodeobj, Managers: Mgrs, Networkbootstrapkeys:d.networkbootstrapkeys,}); Err! = Nil {return err} If disconnect {return Disconnectnode ()}}}
This stream
is a processing agent
connection. The first half is a record of the connected agent
, and the second half is if the cluster
message changes, such as leader
for manager
Changes, you need to notify the agent
to reconnect. The disconnectnode ()
function is a process that needs to be disconnected from the agent node
: including disconnection, agent node
information removal, and so on.