github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/les/flowcontrol/control.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2016 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 //包流控制实现客户端流控制机制 26 package flowcontrol 27 28 import ( 29 "sync" 30 "time" 31 32 "github.com/ethereum/go-ethereum/common/mclock" 33 ) 34 35 const fcTimeConst = time.Millisecond 36 37 type ServerParams struct { 38 BufLimit, MinRecharge uint64 39 } 40 41 type ClientNode struct { 42 params *ServerParams 43 bufValue uint64 44 lastTime mclock.AbsTime 45 lock sync.Mutex 46 cm *ClientManager 47 cmNode *cmNode 48 } 49 50 func NewClientNode(cm *ClientManager, params *ServerParams) *ClientNode { 51 node := &ClientNode{ 52 cm: cm, 53 params: params, 54 bufValue: params.BufLimit, 55 lastTime: mclock.Now(), 56 } 57 node.cmNode = cm.addNode(node) 58 return node 59 } 60 61 func (peer *ClientNode) Remove(cm *ClientManager) { 62 cm.removeNode(peer.cmNode) 63 } 64 65 func (peer *ClientNode) recalcBV(time mclock.AbsTime) { 66 dt := uint64(time - peer.lastTime) 67 if time < peer.lastTime { 68 dt = 0 69 } 70 peer.bufValue += peer.params.MinRecharge * dt / uint64(fcTimeConst) 71 if peer.bufValue > peer.params.BufLimit { 72 peer.bufValue = peer.params.BufLimit 73 } 74 peer.lastTime = time 75 } 76 77 func (peer *ClientNode) AcceptRequest() (uint64, bool) { 78 peer.lock.Lock() 79 defer peer.lock.Unlock() 80 81 time := mclock.Now() 82 peer.recalcBV(time) 83 return peer.bufValue, peer.cm.accept(peer.cmNode, time) 84 } 85 86 func (peer *ClientNode) RequestProcessed(cost uint64) (bv, realCost uint64) { 87 peer.lock.Lock() 88 defer peer.lock.Unlock() 89 90 time := mclock.Now() 91 peer.recalcBV(time) 92 peer.bufValue -= cost 93 peer.recalcBV(time) 94 rcValue, rcost := peer.cm.processed(peer.cmNode, time) 95 if rcValue < peer.params.BufLimit { 96 bv := peer.params.BufLimit - rcValue 97 if bv > peer.bufValue { 98 peer.bufValue = bv 99 } 100 } 101 return peer.bufValue, rcost 102 } 103 104 type ServerNode struct { 105 bufEstimate uint64 106 lastTime mclock.AbsTime 107 params *ServerParams 108 sumCost uint64 //发送到此服务器的请求成本总和 109 pending map[uint64]uint64 //值=发送给定需求后的总成本 110 lock sync.RWMutex 111 } 112 113 func NewServerNode(params *ServerParams) *ServerNode { 114 return &ServerNode{ 115 bufEstimate: params.BufLimit, 116 lastTime: mclock.Now(), 117 params: params, 118 pending: make(map[uint64]uint64), 119 } 120 } 121 122 func (peer *ServerNode) recalcBLE(time mclock.AbsTime) { 123 dt := uint64(time - peer.lastTime) 124 if time < peer.lastTime { 125 dt = 0 126 } 127 peer.bufEstimate += peer.params.MinRecharge * dt / uint64(fcTimeConst) 128 if peer.bufEstimate > peer.params.BufLimit { 129 peer.bufEstimate = peer.params.BufLimit 130 } 131 peer.lastTime = time 132 } 133 134 //当估计的缓冲区值较低时,将安全裕度添加到流控制等待时间中。 135 const safetyMargin = time.Millisecond 136 137 func (peer *ServerNode) canSend(maxCost uint64) (time.Duration, float64) { 138 peer.recalcBLE(mclock.Now()) 139 maxCost += uint64(safetyMargin) * peer.params.MinRecharge / uint64(fcTimeConst) 140 if maxCost > peer.params.BufLimit { 141 maxCost = peer.params.BufLimit 142 } 143 if peer.bufEstimate >= maxCost { 144 return 0, float64(peer.bufEstimate-maxCost) / float64(peer.params.BufLimit) 145 } 146 return time.Duration((maxCost - peer.bufEstimate) * uint64(fcTimeConst) / peer.params.MinRecharge), 0 147 } 148 149 //cansend返回发送请求前所需的最小等待时间 150 //以给定的最大估计成本。第二个返回值是相对值 151 //发送请求后的估计缓冲区级别(除以buflimit)。 152 func (peer *ServerNode) CanSend(maxCost uint64) (time.Duration, float64) { 153 peer.lock.RLock() 154 defer peer.lock.RUnlock() 155 156 return peer.canSend(maxCost) 157 } 158 159 //当请求已分配给给定的 160 //服务器节点,然后将其放入发送队列。必须要求 161 //以与发出QueuerRequest调用相同的顺序发送。 162 func (peer *ServerNode) QueueRequest(reqID, maxCost uint64) { 163 peer.lock.Lock() 164 defer peer.lock.Unlock() 165 166 peer.bufEstimate -= maxCost 167 peer.sumCost += maxCost 168 peer.pending[reqID] = peer.sumCost 169 } 170 171 //gotmreply根据包含在 172 //最新的请求回复。 173 func (peer *ServerNode) GotReply(reqID, bv uint64) { 174 175 peer.lock.Lock() 176 defer peer.lock.Unlock() 177 178 if bv > peer.params.BufLimit { 179 bv = peer.params.BufLimit 180 } 181 sc, ok := peer.pending[reqID] 182 if !ok { 183 return 184 } 185 delete(peer.pending, reqID) 186 cc := peer.sumCost - sc 187 peer.bufEstimate = 0 188 if bv > cc { 189 peer.bufEstimate = bv - cc 190 } 191 peer.lastTime = mclock.Now() 192 }