和etcd连接之后,etcd每多一个key-value就代表多了一个服务器连接到整个系统上来了,这时候就要本服务建立一条与之直连的grcp连接,这个类负责建立和维护这些连接 ---- ===== grcp.ClientConn ===== 原生的grcp连接对象 ---- ===== RPCClient ===== 经过包装的RPC连接对象\\ →(a)**key:string**\\ →→路径,比如:/backends/agent/agent1 →(a)**conn:*grpc.ClientConn**\\ →→底层的连接对象 →(a)**addr:string**\\ →→RPC服务器地址,比如:127.0.0.1:8001 ---- ===== service ===== →(a)**clients:[]RPCClient**\\ →→同一个path的客户端列表 →(a)**idx:uint32**\\ →→id ---- ===== ServicePool ===== →(a)**root:string**\\ →→etcd服务的根路径,比如/backends →(a)**services:map[string]*service**\\ →→key-RPCClient,保存本服和其他所有的GRPC连接 →(a)**etcdClient:*clientv3.Client**\\ →→本服务和etcd服务器连接的原生对象 →(a)**me:*Service**\\ →→本服务和etcd服务器连接对象 →(a)**watchFirst:map[string]bool**\\ →→和getServerFirst方法配合来处理服务启动时,etcd上已经存在的要监控的连接 →(fs)**Init(endpoints:[]string,root:string,watchPath:[]string,me:*Service)**\\ →→单例方法,构造唯一单例,并且调用单例的init方法来初始化,参数直接往下传递 →(f)**init(endpoints:[]string,root:string,watchPath:[]string,me:*Service)*ServiecePool**\\ →→对象初始化,同时开始监控watchPath * endpoints指的是etcd服务器的地址,比如:127.0.0.1:2379。 * root指的是etcd上的根路径,比如:/backends。 * watchPath指的是指的是本服务监控的路径 * me指的是本服务和etcd建立的连接对象 →(f)(go)**WatchNodes(except,path:string)*ServiecePool**\\ →→[go]方法,开启etcd对于path的监控,并且处理监控的结果,如果有etcd新加入的key-value就调用addService方法,并且处理回调,如果是etcd的key-value被删除就调用removeService方法,同样处理回调。在开启监控前会调用getServerFirst先确认一下path下是否已经有key-value →(f)**getServerFirst(path string)**\\ →→这个path就是wathpath,这个方法是为了在确保服务启动前,etcd上已经存在的path要加入到我们的系统中,查询这个path如果能查询到对应的key-value就调用addServer →(f)**addServer(key:string,value:string)**\\ →→关键方法,要加入另外的一个服务,这个key就是这个服务的路径,比如/backends/agent/agent1。这个vaule就是服务的GRPC服务器地址,比如127.0.0.1:8001。拿到这个value之后在这个方法中直接调用GRPC的拨号方法Dial,来生成一个grcp.ClientConn对象,然后把这个原生对象包装成RPCClient,至此拿到一个key-RPCClient,再把这个键值对放入到map对象中 →(f)**removeServer(key:string)*RPCCLient**\\ →→addServer的逆方法,当一个服务从系统中退出的时候,也要关掉对应GRPC连接 →(f)**getServiceWithID(path:string,id:string)*grcp.ClientConn**\\ →→path类似于/backends/agent/,id类似于agent1,组装成完整的path从map中取值 →(f)**getService(path:string)(conn *grcp.ClientConn,key string)**\\ →→从map中取值 →(f)**GetServiceDir(path:string)(map[string]*grcp.ClientConn,bool)**\\ →→从map中取值 →(f)**GetAllService()(map[string]*grcp.ClientConn,bool)**\\ →→从map中取值 →(f)**getServiceDirRPCClient(path:string)(map[string]*RPCClient,bool)**\\ →→从map中取值 →(fs)**GetService(path:string)*grcp.ClientConn**\\ →→包装方法,从_defaultPool中取值 →(fs)**GetServiceWithID(path:string,id:string)*grcp.ClientConn**\\ →→包装方法,从_defaultPool中取值 →(fs)**GetServiceDirRPCClient(path:string)(map[string]*RPCClient,bool)**\\ →→包装方法,从_defaultPool中取值 ===== Instance ===== 此包下的单例对象,go的单例都是用类似的方式来处理\\ →(a)**_defaultPool:ServicePool**\\ →→单例对象 →(a)**once:sync.Once**\\ →→同步对象