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