github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/downloader/peer.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  //版权所有2015 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  //以及信誉指标,以确定块检索的优先级。
    27  
    28  package downloader
    29  
    30  import (
    31  	"errors"
    32  	"fmt"
    33  	"math"
    34  	"math/big"
    35  	"sort"
    36  	"sync"
    37  	"sync/atomic"
    38  	"time"
    39  
    40  	"github.com/ethereum/go-ethereum/common"
    41  	"github.com/ethereum/go-ethereum/event"
    42  	"github.com/ethereum/go-ethereum/log"
    43  )
    44  
    45  const (
    46  maxLackingHashes  = 4096 //列表中允许或缺少项的最大项数
    47  measurementImpact = 0.1  //单个度量对对等端最终吞吐量值的影响。
    48  )
    49  
    50  var (
    51  	errAlreadyFetching   = errors.New("already fetching blocks from peer")
    52  	errAlreadyRegistered = errors.New("peer is already registered")
    53  	errNotRegistered     = errors.New("peer is not registered")
    54  )
    55  
    56  //对等连接表示从中检索哈希和块的活动对等。
    57  type peerConnection struct {
    58  id string //对等方的唯一标识符
    59  
    60  headerIdle  int32 //对等机的当前头活动状态(空闲=0,活动=1)
    61  blockIdle   int32 //对等机的当前块活动状态(空闲=0,活动=1)
    62  receiptIdle int32 //对等机的当前接收活动状态(空闲=0,活动=1)
    63  stateIdle   int32 //对等机的当前节点数据活动状态(空闲=0,活动=1)
    64  
    65  headerThroughput  float64 //每秒可检索的头数
    66  blockThroughput   float64 //每秒可检索的块(体)数
    67  receiptThroughput float64 //每秒可检索的接收数
    68  stateThroughput   float64 //每秒可检索的节点数据块数
    69  
    70  rtt time.Duration //请求往返时间以跟踪响应(QoS)
    71  
    72  headerStarted  time.Time //上次头提取开始时的时间实例
    73  blockStarted   time.Time //上次块(体)提取开始时的时间实例
    74  receiptStarted time.Time //上次接收提取开始时的时间实例
    75  stateStarted   time.Time //上次节点数据提取开始时的时间实例
    76  
    77  lacking map[common.Hash]struct{} //不请求的哈希集(以前没有)
    78  
    79  	peer Peer
    80  
    81  version int        //ETH协议版本号转换策略
    82  log     log.Logger //上下文记录器,用于向对等日志添加额外信息
    83  	lock    sync.RWMutex
    84  }
    85  
    86  //light peer封装了与远程light peer同步所需的方法。
    87  type LightPeer interface {
    88  	Head() (common.Hash, *big.Int)
    89  	RequestHeadersByHash(common.Hash, int, int, bool) error
    90  	RequestHeadersByNumber(uint64, int, int, bool) error
    91  }
    92  
    93  //对等体封装了与远程完整对等体同步所需的方法。
    94  type Peer interface {
    95  	LightPeer
    96  	RequestBodies([]common.Hash) error
    97  	RequestReceipts([]common.Hash) error
    98  	RequestNodeData([]common.Hash) error
    99  }
   100  
   101  //LightPeerWrapper包装了一个LightPeer结构,删除了仅限对等的方法。
   102  type lightPeerWrapper struct {
   103  	peer LightPeer
   104  }
   105  
   106  func (w *lightPeerWrapper) Head() (common.Hash, *big.Int) { return w.peer.Head() }
   107  func (w *lightPeerWrapper) RequestHeadersByHash(h common.Hash, amount int, skip int, reverse bool) error {
   108  	return w.peer.RequestHeadersByHash(h, amount, skip, reverse)
   109  }
   110  func (w *lightPeerWrapper) RequestHeadersByNumber(i uint64, amount int, skip int, reverse bool) error {
   111  	return w.peer.RequestHeadersByNumber(i, amount, skip, reverse)
   112  }
   113  func (w *lightPeerWrapper) RequestBodies([]common.Hash) error {
   114  	panic("RequestBodies not supported in light client mode sync")
   115  }
   116  func (w *lightPeerWrapper) RequestReceipts([]common.Hash) error {
   117  	panic("RequestReceipts not supported in light client mode sync")
   118  }
   119  func (w *lightPeerWrapper) RequestNodeData([]common.Hash) error {
   120  	panic("RequestNodeData not supported in light client mode sync")
   121  }
   122  
   123  //NexPeRead创建了一个新的下载器对等体。
   124  func newPeerConnection(id string, version int, peer Peer, logger log.Logger) *peerConnection {
   125  	return &peerConnection{
   126  		id:      id,
   127  		lacking: make(map[common.Hash]struct{}),
   128  
   129  		peer: peer,
   130  
   131  		version: version,
   132  		log:     logger,
   133  	}
   134  }
   135  
   136  //重置清除对等实体的内部状态。
   137  func (p *peerConnection) Reset() {
   138  	p.lock.Lock()
   139  	defer p.lock.Unlock()
   140  
   141  	atomic.StoreInt32(&p.headerIdle, 0)
   142  	atomic.StoreInt32(&p.blockIdle, 0)
   143  	atomic.StoreInt32(&p.receiptIdle, 0)
   144  	atomic.StoreInt32(&p.stateIdle, 0)
   145  
   146  	p.headerThroughput = 0
   147  	p.blockThroughput = 0
   148  	p.receiptThroughput = 0
   149  	p.stateThroughput = 0
   150  
   151  	p.lacking = make(map[common.Hash]struct{})
   152  }
   153  
   154  //fetchheaders向远程对等端发送头检索请求。
   155  func (p *peerConnection) FetchHeaders(from uint64, count int) error {
   156  //健全性检查协议版本
   157  	if p.version < 62 {
   158  		panic(fmt.Sprintf("header fetch [eth/62+] requested on eth/%d", p.version))
   159  	}
   160  //如果对等机已获取,则短路
   161  	if !atomic.CompareAndSwapInt32(&p.headerIdle, 0, 1) {
   162  		return errAlreadyFetching
   163  	}
   164  	p.headerStarted = time.Now()
   165  
   166  //发出头检索请求(绝对向上,无间隙)
   167  	go p.peer.RequestHeadersByNumber(from, count, 0, false)
   168  
   169  	return nil
   170  }
   171  
   172  //fetchbodies向远程对等端发送一个块体检索请求。
   173  func (p *peerConnection) FetchBodies(request *fetchRequest) error {
   174  //健全性检查协议版本
   175  	if p.version < 62 {
   176  		panic(fmt.Sprintf("body fetch [eth/62+] requested on eth/%d", p.version))
   177  	}
   178  //如果对等机已获取,则短路
   179  	if !atomic.CompareAndSwapInt32(&p.blockIdle, 0, 1) {
   180  		return errAlreadyFetching
   181  	}
   182  	p.blockStarted = time.Now()
   183  
   184  //将标题集转换为可检索切片
   185  	hashes := make([]common.Hash, 0, len(request.Headers))
   186  	for _, header := range request.Headers {
   187  		hashes = append(hashes, header.Hash())
   188  	}
   189  	go p.peer.RequestBodies(hashes)
   190  
   191  	return nil
   192  }
   193  
   194  //fetchreceipts向远程对等发送收据检索请求。
   195  func (p *peerConnection) FetchReceipts(request *fetchRequest) error {
   196  //健全性检查协议版本
   197  	if p.version < 63 {
   198  		panic(fmt.Sprintf("body fetch [eth/63+] requested on eth/%d", p.version))
   199  	}
   200  //如果对等机已获取,则短路
   201  	if !atomic.CompareAndSwapInt32(&p.receiptIdle, 0, 1) {
   202  		return errAlreadyFetching
   203  	}
   204  	p.receiptStarted = time.Now()
   205  
   206  //将标题集转换为可检索切片
   207  	hashes := make([]common.Hash, 0, len(request.Headers))
   208  	for _, header := range request.Headers {
   209  		hashes = append(hashes, header.Hash())
   210  	}
   211  	go p.peer.RequestReceipts(hashes)
   212  
   213  	return nil
   214  }
   215  
   216  //FETCHNODEDATA向远程对等体发送节点状态数据检索请求。
   217  func (p *peerConnection) FetchNodeData(hashes []common.Hash) error {
   218  //健全性检查协议版本
   219  	if p.version < 63 {
   220  		panic(fmt.Sprintf("node data fetch [eth/63+] requested on eth/%d", p.version))
   221  	}
   222  //如果对等机已获取,则短路
   223  	if !atomic.CompareAndSwapInt32(&p.stateIdle, 0, 1) {
   224  		return errAlreadyFetching
   225  	}
   226  	p.stateStarted = time.Now()
   227  
   228  	go p.peer.RequestNodeData(hashes)
   229  
   230  	return nil
   231  }
   232  
   233  //setheadersidle将对等机设置为空闲,允许它执行新的头检索
   234  //请求。它的估计头检索吞吐量用测量值更新。
   235  //刚才。
   236  func (p *peerConnection) SetHeadersIdle(delivered int) {
   237  	p.setIdle(p.headerStarted, delivered, &p.headerThroughput, &p.headerIdle)
   238  }
   239  
   240  //setblocksidle将对等机设置为空闲,允许它执行新的块检索
   241  //请求。它的估计块检索吞吐量用测量的更新。
   242  //刚才。
   243  func (p *peerConnection) SetBlocksIdle(delivered int) {
   244  	p.setIdle(p.blockStarted, delivered, &p.blockThroughput, &p.blockIdle)
   245  }
   246  
   247  //setbodiesidle将对等机设置为空闲,允许它执行块体检索。
   248  //请求。它的估计身体检索吞吐量是用测量值更新的。
   249  //刚才。
   250  func (p *peerConnection) SetBodiesIdle(delivered int) {
   251  	p.setIdle(p.blockStarted, delivered, &p.blockThroughput, &p.blockIdle)
   252  }
   253  
   254  //setReceiptSidle将对等机设置为空闲,允许它执行新的接收
   255  //检索请求。更新其估计的收据检索吞吐量
   256  //刚刚测量的。
   257  func (p *peerConnection) SetReceiptsIdle(delivered int) {
   258  	p.setIdle(p.receiptStarted, delivered, &p.receiptThroughput, &p.receiptIdle)
   259  }
   260  
   261  //setnodedataidle将对等机设置为空闲,允许它执行新的状态trie
   262  //数据检索请求。它的估计状态检索吞吐量被更新
   263  //刚刚测量的。
   264  func (p *peerConnection) SetNodeDataIdle(delivered int) {
   265  	p.setIdle(p.stateStarted, delivered, &p.stateThroughput, &p.stateIdle)
   266  }
   267  
   268  //setidle将对等机设置为idle,允许它执行新的检索请求。
   269  //它的估计检索吞吐量用刚才测量的更新。
   270  func (p *peerConnection) setIdle(started time.Time, delivered int, throughput *float64, idle *int32) {
   271  //与扩展无关,确保对等端最终空闲
   272  	defer atomic.StoreInt32(idle, 0)
   273  
   274  	p.lock.Lock()
   275  	defer p.lock.Unlock()
   276  
   277  //如果没有发送任何内容(硬超时/不可用数据),则将吞吐量降至最低
   278  	if delivered == 0 {
   279  		*throughput = 0
   280  		return
   281  	}
   282  //否则,以新的测量来更新吞吐量。
   283  elapsed := time.Since(started) + 1 //+1(ns)以确保非零除数
   284  	measured := float64(delivered) / (float64(elapsed) / float64(time.Second))
   285  
   286  	*throughput = (1-measurementImpact)*(*throughput) + measurementImpact*measured
   287  	p.rtt = time.Duration((1-measurementImpact)*float64(p.rtt) + measurementImpact*float64(elapsed))
   288  
   289  	p.log.Trace("Peer throughput measurements updated",
   290  		"hps", p.headerThroughput, "bps", p.blockThroughput,
   291  		"rps", p.receiptThroughput, "sps", p.stateThroughput,
   292  		"miss", len(p.lacking), "rtt", p.rtt)
   293  }
   294  
   295  //HeaderCapacity根据其
   296  //以前发现的吞吐量。
   297  func (p *peerConnection) HeaderCapacity(targetRTT time.Duration) int {
   298  	p.lock.RLock()
   299  	defer p.lock.RUnlock()
   300  
   301  	return int(math.Min(1+math.Max(1, p.headerThroughput*float64(targetRTT)/float64(time.Second)), float64(MaxHeaderFetch)))
   302  }
   303  
   304  //BlockCapacity根据其
   305  //以前发现的吞吐量。
   306  func (p *peerConnection) BlockCapacity(targetRTT time.Duration) int {
   307  	p.lock.RLock()
   308  	defer p.lock.RUnlock()
   309  
   310  	return int(math.Min(1+math.Max(1, p.blockThroughput*float64(targetRTT)/float64(time.Second)), float64(MaxBlockFetch)))
   311  }
   312  
   313  //ReceiptCapacity根据其
   314  //以前发现的吞吐量。
   315  func (p *peerConnection) ReceiptCapacity(targetRTT time.Duration) int {
   316  	p.lock.RLock()
   317  	defer p.lock.RUnlock()
   318  
   319  	return int(math.Min(1+math.Max(1, p.receiptThroughput*float64(targetRTT)/float64(time.Second)), float64(MaxReceiptFetch)))
   320  }
   321  
   322  //nodeDataCapacity根据其
   323  //以前发现的吞吐量。
   324  func (p *peerConnection) NodeDataCapacity(targetRTT time.Duration) int {
   325  	p.lock.RLock()
   326  	defer p.lock.RUnlock()
   327  
   328  	return int(math.Min(1+math.Max(1, p.stateThroughput*float64(targetRTT)/float64(time.Second)), float64(MaxStateFetch)))
   329  }
   330  
   331  //MaxDebug将新实体添加到一组项目(块、收据、状态)中。
   332  //已知某个对等机没有(即之前已被请求)。如果
   333  //集合达到其最大允许容量,项目被随机丢弃。
   334  func (p *peerConnection) MarkLacking(hash common.Hash) {
   335  	p.lock.Lock()
   336  	defer p.lock.Unlock()
   337  
   338  	for len(p.lacking) >= maxLackingHashes {
   339  		for drop := range p.lacking {
   340  			delete(p.lacking, drop)
   341  			break
   342  		}
   343  	}
   344  	p.lacking[hash] = struct{}{}
   345  }
   346  
   347  //缺少检索区块链项目的哈希是否在缺少的对等项上
   348  //列出(即,我们是否知道同伴没有它)。
   349  func (p *peerConnection) Lacks(hash common.Hash) bool {
   350  	p.lock.RLock()
   351  	defer p.lock.RUnlock()
   352  
   353  	_, ok := p.lacking[hash]
   354  	return ok
   355  }
   356  
   357  //对等集表示参与链的活动对等集
   358  //下载过程。
   359  type peerSet struct {
   360  	peers        map[string]*peerConnection
   361  	newPeerFeed  event.Feed
   362  	peerDropFeed event.Feed
   363  	lock         sync.RWMutex
   364  }
   365  
   366  //new peer set创建一个新的peer set top跟踪活动的下载源。
   367  func newPeerSet() *peerSet {
   368  	return &peerSet{
   369  		peers: make(map[string]*peerConnection),
   370  	}
   371  }
   372  
   373  //订阅方订阅对等到达事件。
   374  func (ps *peerSet) SubscribeNewPeers(ch chan<- *peerConnection) event.Subscription {
   375  	return ps.newPeerFeed.Subscribe(ch)
   376  }
   377  
   378  //订阅对等删除订阅对等离开事件。
   379  func (ps *peerSet) SubscribePeerDrops(ch chan<- *peerConnection) event.Subscription {
   380  	return ps.peerDropFeed.Subscribe(ch)
   381  }
   382  
   383  //重置迭代当前对等集,并重置每个已知对等
   384  //为下一批块检索做准备。
   385  func (ps *peerSet) Reset() {
   386  	ps.lock.RLock()
   387  	defer ps.lock.RUnlock()
   388  
   389  	for _, peer := range ps.peers {
   390  		peer.Reset()
   391  	}
   392  }
   393  
   394  //寄存器向工作集中注入一个新的对等点,或者返回一个错误,如果
   395  //对等机已经知道。
   396  //
   397  //该方法还将新对等机的起始吞吐量值设置为
   398  //对所有现有同龄人的平均数,以使其有实际的使用机会
   399  //用于数据检索。
   400  func (ps *peerSet) Register(p *peerConnection) error {
   401  //检索当前中间值RTT作为健全的默认值
   402  	p.rtt = ps.medianRTT()
   403  
   404  //用一些有意义的默认值注册新的对等机
   405  	ps.lock.Lock()
   406  	if _, ok := ps.peers[p.id]; ok {
   407  		ps.lock.Unlock()
   408  		return errAlreadyRegistered
   409  	}
   410  	if len(ps.peers) > 0 {
   411  		p.headerThroughput, p.blockThroughput, p.receiptThroughput, p.stateThroughput = 0, 0, 0, 0
   412  
   413  		for _, peer := range ps.peers {
   414  			peer.lock.RLock()
   415  			p.headerThroughput += peer.headerThroughput
   416  			p.blockThroughput += peer.blockThroughput
   417  			p.receiptThroughput += peer.receiptThroughput
   418  			p.stateThroughput += peer.stateThroughput
   419  			peer.lock.RUnlock()
   420  		}
   421  		p.headerThroughput /= float64(len(ps.peers))
   422  		p.blockThroughput /= float64(len(ps.peers))
   423  		p.receiptThroughput /= float64(len(ps.peers))
   424  		p.stateThroughput /= float64(len(ps.peers))
   425  	}
   426  	ps.peers[p.id] = p
   427  	ps.lock.Unlock()
   428  
   429  	ps.newPeerFeed.Send(p)
   430  	return nil
   431  }
   432  
   433  //注销从活动集删除远程对等,进一步禁用
   434  //对该特定实体采取的行动。
   435  func (ps *peerSet) Unregister(id string) error {
   436  	ps.lock.Lock()
   437  	p, ok := ps.peers[id]
   438  	if !ok {
   439  		defer ps.lock.Unlock()
   440  		return errNotRegistered
   441  	}
   442  	delete(ps.peers, id)
   443  	ps.lock.Unlock()
   444  
   445  	ps.peerDropFeed.Send(p)
   446  	return nil
   447  }
   448  
   449  //对等端检索具有给定ID的注册对等端。
   450  func (ps *peerSet) Peer(id string) *peerConnection {
   451  	ps.lock.RLock()
   452  	defer ps.lock.RUnlock()
   453  
   454  	return ps.peers[id]
   455  }
   456  
   457  //len返回集合中当前的对等数。
   458  func (ps *peerSet) Len() int {
   459  	ps.lock.RLock()
   460  	defer ps.lock.RUnlock()
   461  
   462  	return len(ps.peers)
   463  }
   464  
   465  //Allpeers检索集合中所有对等方的简单列表。
   466  func (ps *peerSet) AllPeers() []*peerConnection {
   467  	ps.lock.RLock()
   468  	defer ps.lock.RUnlock()
   469  
   470  	list := make([]*peerConnection, 0, len(ps.peers))
   471  	for _, p := range ps.peers {
   472  		list = append(list, p)
   473  	}
   474  	return list
   475  }
   476  
   477  //HeaderIdlePeers检索当前所有头空闲对等的简单列表
   478  //在活动对等集内,按其声誉排序。
   479  func (ps *peerSet) HeaderIdlePeers() ([]*peerConnection, int) {
   480  	idle := func(p *peerConnection) bool {
   481  		return atomic.LoadInt32(&p.headerIdle) == 0
   482  	}
   483  	throughput := func(p *peerConnection) float64 {
   484  		p.lock.RLock()
   485  		defer p.lock.RUnlock()
   486  		return p.headerThroughput
   487  	}
   488  	return ps.idlePeers(62, 64, idle, throughput)
   489  }
   490  
   491  //BodyIdlePeers检索当前位于
   492  //按其声誉排序的活动对等集。
   493  func (ps *peerSet) BodyIdlePeers() ([]*peerConnection, int) {
   494  	idle := func(p *peerConnection) bool {
   495  		return atomic.LoadInt32(&p.blockIdle) == 0
   496  	}
   497  	throughput := func(p *peerConnection) float64 {
   498  		p.lock.RLock()
   499  		defer p.lock.RUnlock()
   500  		return p.blockThroughput
   501  	}
   502  	return ps.idlePeers(62, 64, idle, throughput)
   503  }
   504  
   505  //ReceiptIdlePeers检索当前所有接收空闲对等的简单列表
   506  //在活动对等集内,按其声誉排序。
   507  func (ps *peerSet) ReceiptIdlePeers() ([]*peerConnection, int) {
   508  	idle := func(p *peerConnection) bool {
   509  		return atomic.LoadInt32(&p.receiptIdle) == 0
   510  	}
   511  	throughput := func(p *peerConnection) float64 {
   512  		p.lock.RLock()
   513  		defer p.lock.RUnlock()
   514  		return p.receiptThroughput
   515  	}
   516  	return ps.idlePeers(63, 64, idle, throughput)
   517  }
   518  
   519  //nodedataidlepeers检索当前所有空闲节点数据的简单列表
   520  //活动对等集内的对等点,按其声誉排序。
   521  func (ps *peerSet) NodeDataIdlePeers() ([]*peerConnection, int) {
   522  	idle := func(p *peerConnection) bool {
   523  		return atomic.LoadInt32(&p.stateIdle) == 0
   524  	}
   525  	throughput := func(p *peerConnection) float64 {
   526  		p.lock.RLock()
   527  		defer p.lock.RUnlock()
   528  		return p.stateThroughput
   529  	}
   530  	return ps.idlePeers(63, 64, idle, throughput)
   531  }
   532  
   533  //idle peers检索当前满足
   534  //协议版本约束,使用提供的函数检查空闲。
   535  //由此产生的一组对等机按其度量吞吐量进行排序。
   536  func (ps *peerSet) idlePeers(minProtocol, maxProtocol int, idleCheck func(*peerConnection) bool, throughput func(*peerConnection) float64) ([]*peerConnection, int) {
   537  	ps.lock.RLock()
   538  	defer ps.lock.RUnlock()
   539  
   540  	idle, total := make([]*peerConnection, 0, len(ps.peers)), 0
   541  	for _, p := range ps.peers {
   542  		if p.version >= minProtocol && p.version <= maxProtocol {
   543  			if idleCheck(p) {
   544  				idle = append(idle, p)
   545  			}
   546  			total++
   547  		}
   548  	}
   549  	for i := 0; i < len(idle); i++ {
   550  		for j := i + 1; j < len(idle); j++ {
   551  			if throughput(idle[i]) < throughput(idle[j]) {
   552  				idle[i], idle[j] = idle[j], idle[i]
   553  			}
   554  		}
   555  	}
   556  	return idle, total
   557  }
   558  
   559  //MediaNRTT返回对等集的中间RTT,只考虑调优
   560  //如果有更多可用的对等机,则为对等机。
   561  func (ps *peerSet) medianRTT() time.Duration {
   562  //收集所有当前测量的往返时间
   563  	ps.lock.RLock()
   564  	defer ps.lock.RUnlock()
   565  
   566  	rtts := make([]float64, 0, len(ps.peers))
   567  	for _, p := range ps.peers {
   568  		p.lock.RLock()
   569  		rtts = append(rtts, float64(p.rtt))
   570  		p.lock.RUnlock()
   571  	}
   572  	sort.Float64s(rtts)
   573  
   574  	median := rttMaxEstimate
   575  	if qosTuningPeers <= len(rtts) {
   576  median = time.Duration(rtts[qosTuningPeers/2]) //调优同行的中位数
   577  	} else if len(rtts) > 0 {
   578  median = time.Duration(rtts[len(rtts)/2]) //我们连接的对等点的中位数(甚至保持一些基线QoS)
   579  	}
   580  //将RTT限制为一些QoS默认值,与真正的RTT无关
   581  	if median < rttMinEstimate {
   582  		median = rttMinEstimate
   583  	}
   584  	if median > rttMaxEstimate {
   585  		median = rttMaxEstimate
   586  	}
   587  	return median
   588  }