github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/les/flowcontrol/manager.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:40</date> 10 //</624342643630936064> 11 12 13 //包流控制实现客户端流控制机制 14 package flowcontrol 15 16 import ( 17 "sync" 18 "time" 19 20 "github.com/ethereum/go-ethereum/common/mclock" 21 ) 22 23 const rcConst = 1000000 24 25 type cmNode struct { 26 node *ClientNode 27 lastUpdate mclock.AbsTime 28 serving, recharging bool 29 rcWeight uint64 30 rcValue, rcDelta, startValue int64 31 finishRecharge mclock.AbsTime 32 } 33 34 func (node *cmNode) update(time mclock.AbsTime) { 35 dt := int64(time - node.lastUpdate) 36 node.rcValue += node.rcDelta * dt / rcConst 37 node.lastUpdate = time 38 if node.recharging && time >= node.finishRecharge { 39 node.recharging = false 40 node.rcDelta = 0 41 node.rcValue = 0 42 } 43 } 44 45 func (node *cmNode) set(serving bool, simReqCnt, sumWeight uint64) { 46 if node.serving && !serving { 47 node.recharging = true 48 sumWeight += node.rcWeight 49 } 50 node.serving = serving 51 if node.recharging && serving { 52 node.recharging = false 53 sumWeight -= node.rcWeight 54 } 55 56 node.rcDelta = 0 57 if serving { 58 node.rcDelta = int64(rcConst / simReqCnt) 59 } 60 if node.recharging { 61 node.rcDelta = -int64(node.node.cm.rcRecharge * node.rcWeight / sumWeight) 62 node.finishRecharge = node.lastUpdate + mclock.AbsTime(node.rcValue*rcConst/(-node.rcDelta)) 63 } 64 } 65 66 type ClientManager struct { 67 lock sync.Mutex 68 nodes map[*cmNode]struct{} 69 simReqCnt, sumWeight, rcSumValue uint64 70 maxSimReq, maxRcSum uint64 71 rcRecharge uint64 72 resumeQueue chan chan bool 73 time mclock.AbsTime 74 } 75 76 func NewClientManager(rcTarget, maxSimReq, maxRcSum uint64) *ClientManager { 77 cm := &ClientManager{ 78 nodes: make(map[*cmNode]struct{}), 79 resumeQueue: make(chan chan bool), 80 rcRecharge: rcConst * rcConst / (100*rcConst/rcTarget - rcConst), 81 maxSimReq: maxSimReq, 82 maxRcSum: maxRcSum, 83 } 84 go cm.queueProc() 85 return cm 86 } 87 88 func (self *ClientManager) Stop() { 89 self.lock.Lock() 90 defer self.lock.Unlock() 91 92 //向任何等待接受例程发出返回false的信号 93 self.nodes = make(map[*cmNode]struct{}) 94 close(self.resumeQueue) 95 } 96 97 func (self *ClientManager) addNode(cnode *ClientNode) *cmNode { 98 time := mclock.Now() 99 node := &cmNode{ 100 node: cnode, 101 lastUpdate: time, 102 finishRecharge: time, 103 rcWeight: 1, 104 } 105 self.lock.Lock() 106 defer self.lock.Unlock() 107 108 self.nodes[node] = struct{}{} 109 self.update(mclock.Now()) 110 return node 111 } 112 113 func (self *ClientManager) removeNode(node *cmNode) { 114 self.lock.Lock() 115 defer self.lock.Unlock() 116 117 time := mclock.Now() 118 self.stop(node, time) 119 delete(self.nodes, node) 120 self.update(time) 121 } 122 123 //重新计算总重量 124 func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) { 125 var sumWeight, rcSum uint64 126 for node := range self.nodes { 127 rc := node.recharging 128 node.update(time) 129 if rc && !node.recharging { 130 rce = true 131 } 132 if node.recharging { 133 sumWeight += node.rcWeight 134 } 135 rcSum += uint64(node.rcValue) 136 } 137 self.sumWeight = sumWeight 138 self.rcSumValue = rcSum 139 return 140 } 141 142 func (self *ClientManager) update(time mclock.AbsTime) { 143 for { 144 firstTime := time 145 for node := range self.nodes { 146 if node.recharging && node.finishRecharge < firstTime { 147 firstTime = node.finishRecharge 148 } 149 } 150 if self.updateNodes(firstTime) { 151 for node := range self.nodes { 152 if node.recharging { 153 node.set(node.serving, self.simReqCnt, self.sumWeight) 154 } 155 } 156 } else { 157 self.time = time 158 return 159 } 160 } 161 } 162 163 func (self *ClientManager) canStartReq() bool { 164 return self.simReqCnt < self.maxSimReq && self.rcSumValue < self.maxRcSum 165 } 166 167 func (self *ClientManager) queueProc() { 168 for rc := range self.resumeQueue { 169 for { 170 time.Sleep(time.Millisecond * 10) 171 self.lock.Lock() 172 self.update(mclock.Now()) 173 cs := self.canStartReq() 174 self.lock.Unlock() 175 if cs { 176 break 177 } 178 } 179 close(rc) 180 } 181 } 182 183 func (self *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool { 184 self.lock.Lock() 185 defer self.lock.Unlock() 186 187 self.update(time) 188 if !self.canStartReq() { 189 resume := make(chan bool) 190 self.lock.Unlock() 191 self.resumeQueue <- resume 192 <-resume 193 self.lock.Lock() 194 if _, ok := self.nodes[node]; !ok { 195 return false //如果节点已删除或管理器已停止,则拒绝 196 } 197 } 198 self.simReqCnt++ 199 node.set(true, self.simReqCnt, self.sumWeight) 200 node.startValue = node.rcValue 201 self.update(self.time) 202 return true 203 } 204 205 func (self *ClientManager) stop(node *cmNode, time mclock.AbsTime) { 206 if node.serving { 207 self.update(time) 208 self.simReqCnt-- 209 node.set(false, self.simReqCnt, self.sumWeight) 210 self.update(time) 211 } 212 } 213 214 func (self *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) { 215 self.lock.Lock() 216 defer self.lock.Unlock() 217 218 self.stop(node, time) 219 return uint64(node.rcValue), uint64(node.rcValue - node.startValue) 220 } 221