github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/les/flowcontrol/control.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 //</624342643568021504> 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 fcTimeConst = time.Millisecond 24 25 type ServerParams struct { 26 BufLimit, MinRecharge uint64 27 } 28 29 type ClientNode struct { 30 params *ServerParams 31 bufValue uint64 32 lastTime mclock.AbsTime 33 lock sync.Mutex 34 cm *ClientManager 35 cmNode *cmNode 36 } 37 38 func NewClientNode(cm *ClientManager, params *ServerParams) *ClientNode { 39 node := &ClientNode{ 40 cm: cm, 41 params: params, 42 bufValue: params.BufLimit, 43 lastTime: mclock.Now(), 44 } 45 node.cmNode = cm.addNode(node) 46 return node 47 } 48 49 func (peer *ClientNode) Remove(cm *ClientManager) { 50 cm.removeNode(peer.cmNode) 51 } 52 53 func (peer *ClientNode) recalcBV(time mclock.AbsTime) { 54 dt := uint64(time - peer.lastTime) 55 if time < peer.lastTime { 56 dt = 0 57 } 58 peer.bufValue += peer.params.MinRecharge * dt / uint64(fcTimeConst) 59 if peer.bufValue > peer.params.BufLimit { 60 peer.bufValue = peer.params.BufLimit 61 } 62 peer.lastTime = time 63 } 64 65 func (peer *ClientNode) AcceptRequest() (uint64, bool) { 66 peer.lock.Lock() 67 defer peer.lock.Unlock() 68 69 time := mclock.Now() 70 peer.recalcBV(time) 71 return peer.bufValue, peer.cm.accept(peer.cmNode, time) 72 } 73 74 func (peer *ClientNode) RequestProcessed(cost uint64) (bv, realCost uint64) { 75 peer.lock.Lock() 76 defer peer.lock.Unlock() 77 78 time := mclock.Now() 79 peer.recalcBV(time) 80 peer.bufValue -= cost 81 peer.recalcBV(time) 82 rcValue, rcost := peer.cm.processed(peer.cmNode, time) 83 if rcValue < peer.params.BufLimit { 84 bv := peer.params.BufLimit - rcValue 85 if bv > peer.bufValue { 86 peer.bufValue = bv 87 } 88 } 89 return peer.bufValue, rcost 90 } 91 92 type ServerNode struct { 93 bufEstimate uint64 94 lastTime mclock.AbsTime 95 params *ServerParams 96 sumCost uint64 //发送到此服务器的请求成本总和 97 pending map[uint64]uint64 //值=发送给定需求后的总成本 98 lock sync.RWMutex 99 } 100 101 func NewServerNode(params *ServerParams) *ServerNode { 102 return &ServerNode{ 103 bufEstimate: params.BufLimit, 104 lastTime: mclock.Now(), 105 params: params, 106 pending: make(map[uint64]uint64), 107 } 108 } 109 110 func (peer *ServerNode) recalcBLE(time mclock.AbsTime) { 111 dt := uint64(time - peer.lastTime) 112 if time < peer.lastTime { 113 dt = 0 114 } 115 peer.bufEstimate += peer.params.MinRecharge * dt / uint64(fcTimeConst) 116 if peer.bufEstimate > peer.params.BufLimit { 117 peer.bufEstimate = peer.params.BufLimit 118 } 119 peer.lastTime = time 120 } 121 122 //当估计的缓冲区值较低时,将安全裕度添加到流控制等待时间中。 123 const safetyMargin = time.Millisecond 124 125 func (peer *ServerNode) canSend(maxCost uint64) (time.Duration, float64) { 126 peer.recalcBLE(mclock.Now()) 127 maxCost += uint64(safetyMargin) * peer.params.MinRecharge / uint64(fcTimeConst) 128 if maxCost > peer.params.BufLimit { 129 maxCost = peer.params.BufLimit 130 } 131 if peer.bufEstimate >= maxCost { 132 return 0, float64(peer.bufEstimate-maxCost) / float64(peer.params.BufLimit) 133 } 134 return time.Duration((maxCost - peer.bufEstimate) * uint64(fcTimeConst) / peer.params.MinRecharge), 0 135 } 136 137 //cansend返回发送请求前所需的最小等待时间 138 //以给定的最大估计成本。第二个返回值是相对值 139 //发送请求后的估计缓冲区级别(除以buflimit)。 140 func (peer *ServerNode) CanSend(maxCost uint64) (time.Duration, float64) { 141 peer.lock.RLock() 142 defer peer.lock.RUnlock() 143 144 return peer.canSend(maxCost) 145 } 146 147 //当请求已分配给给定的 148 //服务器节点,然后将其放入发送队列。必须要求 149 //以与发出QueuerRequest调用相同的顺序发送。 150 func (peer *ServerNode) QueueRequest(reqID, maxCost uint64) { 151 peer.lock.Lock() 152 defer peer.lock.Unlock() 153 154 peer.bufEstimate -= maxCost 155 peer.sumCost += maxCost 156 peer.pending[reqID] = peer.sumCost 157 } 158 159 //gotmreply根据包含在 160 //最新的请求回复。 161 func (peer *ServerNode) GotReply(reqID, bv uint64) { 162 163 peer.lock.Lock() 164 defer peer.lock.Unlock() 165 166 if bv > peer.params.BufLimit { 167 bv = peer.params.BufLimit 168 } 169 sc, ok := peer.pending[reqID] 170 if !ok { 171 return 172 } 173 delete(peer.pending, reqID) 174 cc := peer.sumCost - sc 175 peer.bufEstimate = 0 176 if bv > cc { 177 peer.bufEstimate = bv - cc 178 } 179 peer.lastTime = mclock.Now() 180 } 181