github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/manage/conns.go (about) 1 // Package manage p2p manage 2 package manage 3 4 import ( 5 "context" 6 "fmt" 7 "sort" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/turingchain2020/turingchain/common/log/log15" 13 p2pty "github.com/turingchain2020/turingchain/system/p2p/dht/types" 14 "github.com/turingchain2020/turingchain/types" 15 core "github.com/libp2p/go-libp2p-core" 16 "github.com/libp2p/go-libp2p-core/metrics" 17 "github.com/libp2p/go-libp2p-core/network" 18 "github.com/libp2p/go-libp2p-core/peer" 19 kb "github.com/libp2p/go-libp2p-kbucket" 20 "github.com/multiformats/go-multiaddr" 21 ) 22 23 var ( 24 log = log15.New("module", "p2p.connManage") 25 ) 26 27 const ( 28 maxBounds = 30 //最大连接数包含连接被连接 29 maxOutBounds = 15 //对外连接的最大节点数量 30 ) 31 32 // ConnManager p2p connection manager 33 type ConnManager struct { 34 ctx context.Context 35 neighborStore sync.Map 36 host core.Host 37 bandwidthTracker *metrics.BandwidthCounter 38 routingTable *kb.RoutingTable 39 cfg *p2pty.P2PSubConfig 40 } 41 42 // NewConnManager new connection manager 43 func NewConnManager(ctx context.Context, host core.Host, rt *kb.RoutingTable, tracker *metrics.BandwidthCounter, cfg *p2pty.P2PSubConfig) *ConnManager { 44 connM := &ConnManager{} 45 connM.ctx = ctx 46 connM.host = host 47 connM.routingTable = rt 48 connM.bandwidthTracker = tracker 49 connM.cfg = cfg 50 51 return connM 52 53 } 54 55 // RateCalculate means bytes sent / received per second. 56 func (s *ConnManager) RateCalculate(ratebytes float64) string { 57 kbytes := ratebytes / 1024 58 rate := fmt.Sprintf("%.3f KB/s", kbytes) 59 60 if kbytes/1024 > 0.1 { 61 rate = fmt.Sprintf("%.3f MB/s", kbytes/1024) 62 } 63 64 return rate 65 } 66 67 // BandTrackerByProtocol returns all protocols band info 68 func (s *ConnManager) BandTrackerByProtocol() *types.NetProtocolInfos { 69 bandprotocols := s.bandwidthTracker.GetBandwidthByProtocol() 70 var infos netprotocols 71 for id, stat := range bandprotocols { 72 if id == "" || stat.RateIn+stat.RateOut == 0 { 73 continue 74 } 75 var info sortNetProtocols 76 info.Protocol = string(id) 77 info.Ratein = s.RateCalculate(stat.RateIn) 78 info.Rateout = s.RateCalculate(stat.RateOut) 79 info.Ratetotal = s.RateCalculate(stat.RateIn + stat.RateOut) 80 infos = append(infos, &info) 81 } 82 83 sort.Sort(infos) //对Ratetotal 进行排序 84 var netinfoArr []*types.ProtocolInfo 85 for _, info := range infos { 86 var protoinfo types.ProtocolInfo 87 protoinfo.Ratetotal = info.Ratetotal 88 protoinfo.Rateout = info.Rateout 89 protoinfo.Ratein = info.Ratein 90 protoinfo.Protocol = info.Protocol 91 if strings.Contains(protoinfo.Ratetotal, "0.000") { 92 continue 93 } 94 netinfoArr = append(netinfoArr, &protoinfo) 95 } 96 97 return &types.NetProtocolInfos{Protoinfo: netinfoArr} 98 99 } 100 101 // MonitorAllPeers monitory all peers 102 func (s *ConnManager) MonitorAllPeers() { 103 ticker1 := time.NewTicker(time.Minute) 104 ticker2 := time.NewTicker(time.Minute * 2) 105 for { 106 select { 107 case <-s.ctx.Done(): 108 return 109 case <-ticker1.C: 110 s.printMonitorInfo() 111 case <-ticker2.C: 112 s.procConnections() 113 } 114 } 115 } 116 117 func (s *ConnManager) printMonitorInfo() { 118 var LatencyInfo = fmt.Sprintln("--------------时延--------------------") 119 peers := s.FetchConnPeers() 120 bandByPeer := s.bandwidthTracker.GetBandwidthByPeer() 121 var trackerInfo = fmt.Sprintln("------------BandTracker--------------") 122 for _, pid := range peers { 123 //统计每个节点的时延,统计最多MaxBounds个 124 tduration := s.host.Peerstore().LatencyEWMA(pid) 125 if tduration == 0 { 126 continue 127 } 128 LatencyInfo += fmt.Sprintln("PeerID:", pid.Pretty(), "LatencyEWMA:", tduration) 129 if stat, ok := bandByPeer[pid]; ok { 130 trackerInfo += fmt.Sprintf("PeerID:%s,RateIn:%f bytes/s,RateOut:%f bytes/s,totalIn:%d bytes,totalOut:%d\n", 131 pid, 132 stat.RateIn, 133 stat.RateOut, 134 stat.TotalIn, 135 stat.TotalOut) 136 } 137 //protocols rate 138 log.Debug(LatencyInfo) 139 140 insize, outsize := s.BoundSize() 141 trackerInfo += fmt.Sprintln("peerstoreNum:", len(s.host.Peerstore().Peers()), ",conn num:", insize+outsize, "inbound num", insize, "outbound num", outsize, 142 "dht size", s.routingTable.Size()) 143 trackerInfo += fmt.Sprintln("-------------------------------------") 144 log.Debug(trackerInfo) 145 } 146 } 147 148 func (s *ConnManager) procConnections() { 149 //处理当前连接的节点问题 150 _, outBoundSize := s.BoundSize() 151 if outBoundSize > maxOutBounds || s.Size() > maxBounds { 152 return 153 } 154 //如果连接的节点数较少,尝试连接内置的和配置的种子节点 155 //无须担心重新连接的问题,底层会自己判断是否已经连接了此节点,如果已经连接了就会忽略 156 for _, seed := range s.cfg.Seeds { 157 info, err := genAddrInfo(seed) 158 if err != nil { 159 panic(`invalid seeds format in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`) 160 } 161 _ = s.host.Connect(context.Background(), *info) 162 } 163 164 for _, node := range s.cfg.BootStraps { 165 info, err := genAddrInfo(node) 166 if err != nil { 167 panic(`invalid bootStraps format in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`) 168 } 169 _ = s.host.Connect(context.Background(), *info) 170 } 171 if s.cfg.RelayEnable { 172 //对relay中中继服务器要长期保持连接 173 for _, node := range s.cfg.RelayNodeAddr { 174 info, err := genAddrInfo(node) 175 if err != nil { 176 panic(`invalid relayNodeAddr in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`) 177 } 178 if len(s.host.Network().ConnsToPeer(info.ID)) == 0 { 179 s.host.Connect(context.Background(), *info) 180 } 181 } 182 } 183 184 } 185 186 func genAddrInfo(addr string) (*peer.AddrInfo, error) { 187 mAddr, err := multiaddr.NewMultiaddr(addr) 188 if err != nil { 189 return nil, err 190 } 191 return peer.AddrInfoFromP2pAddr(mAddr) 192 } 193 194 // AddNeighbors add neighbors by peer info 195 func (s *ConnManager) AddNeighbors(pr *peer.AddrInfo) { 196 if pr == nil { 197 return 198 } 199 s.neighborStore.Store(pr.ID.Pretty(), pr) 200 } 201 202 // IsNeighbors check is neighbors by id 203 func (s *ConnManager) IsNeighbors(pid peer.ID) bool { 204 _, ok := s.neighborStore.Load(pid.Pretty()) 205 return ok 206 } 207 208 // Delete delete peer by id 209 func (s *ConnManager) Delete(pid peer.ID) { 210 _ = s.host.Network().ClosePeer(pid) 211 s.routingTable.Remove(pid) 212 } 213 214 // FetchNearestPeers fetch nearest peer ids 215 func (s *ConnManager) FetchNearestPeers(count int) []peer.ID { 216 if s.routingTable == nil { 217 return nil 218 } 219 return s.routingTable.NearestPeers(kb.ConvertPeerID(s.host.ID()), count) 220 } 221 222 // Size connections size 223 func (s *ConnManager) Size() int { 224 return len(s.host.Network().Conns()) 225 } 226 227 // FetchConnPeers 获取连接的Peer's ID 这个连接包含被连接的peer以及主动连接的peer. 228 func (s *ConnManager) FetchConnPeers() []peer.ID { 229 var peers = make(map[string]peer.ID) 230 var allconns conns 231 232 for _, conn := range s.host.Network().Conns() { 233 allconns = append(allconns, conn) 234 } 235 236 //对当前连接的节点时长进行排序 237 sort.Sort(allconns) 238 //log.Debug("FetchConnPeers", "stream Num", len(conn.GetStreams()), "pid", conn.RemotePeer().Pretty()) 239 for _, conn := range allconns { 240 peers[conn.RemotePeer().Pretty()] = conn.RemotePeer() 241 if len(peers) >= maxBounds { 242 break 243 } 244 } 245 return convertMapToArr(peers) 246 } 247 248 func convertMapToArr(in map[string]peer.ID) []peer.ID { 249 var pids []peer.ID 250 for _, id := range in { 251 pids = append(pids, id) 252 } 253 return pids 254 } 255 256 // CheckDirection 检查连接的节点ID是被连接的还是主动连接的 257 func (s *ConnManager) CheckDirection(pid peer.ID) network.Direction { 258 for _, conn := range s.host.Network().ConnsToPeer(pid) { 259 return conn.Stat().Direction 260 } 261 return network.DirUnknown 262 } 263 264 // OutBounds get out bounds conn peers 265 func (s *ConnManager) OutBounds() []peer.ID { 266 var peers []peer.ID 267 for _, con := range s.host.Network().Conns() { 268 if con.Stat().Direction == network.DirOutbound { 269 peers = append(peers, con.RemotePeer()) 270 } 271 } 272 return peers 273 } 274 275 // InBounds get in bounds conn peers 276 func (s *ConnManager) InBounds() []peer.ID { 277 var peers []peer.ID 278 for _, con := range s.host.Network().Conns() { 279 if con.Stat().Direction == network.DirInbound { 280 peers = append(peers, con.RemotePeer()) 281 } 282 } 283 return peers 284 } 285 286 // BoundSize get in out conn bound size 287 func (s *ConnManager) BoundSize() (insize int, outsize int) { 288 for _, con := range s.host.Network().Conns() { 289 if con.Stat().Direction == network.DirOutbound { 290 outsize++ 291 } 292 if con.Stat().Direction == network.DirInbound { 293 insize++ 294 } 295 } 296 return insize, outsize 297 } 298 299 // GetNetRate get rateinfo 300 func (s *ConnManager) GetNetRate() metrics.Stats { 301 return s.bandwidthTracker.GetBandwidthTotals() 302 } 303 304 //对系统的连接时长按照从大到小的顺序排序 305 type conns []network.Conn 306 307 //Len 308 func (c conns) Len() int { return len(c) } 309 310 //Swap 311 func (c conns) Swap(i, j int) { c[i], c[j] = c[j], c[i] } 312 313 //Less 314 func (c conns) Less(i, j int) bool { //从大到小排序,即index=0 ,表示数值最大 315 return c[i].Stat().Opened.After(c[j].Stat().Opened) 316 } 317 318 type sortNetProtocols struct { 319 Protocol string 320 Ratetotal string 321 Ratein string 322 Rateout string 323 } 324 325 type netprotocols []*sortNetProtocols 326 327 //Len 328 func (n netprotocols) Len() int { return len(n) } 329 330 //Swap 331 func (n netprotocols) Swap(i, j int) { n[i], n[j] = n[j], n[i] } 332 333 //Less 334 func (n netprotocols) Less(i, j int) bool { //从小到大排序,即index=0 ,表示数值最小 335 return n[i].Ratetotal < n[j].Ratetotal 336 }