p2p: throttle all discovery lookups

Lookup calls would spin out of control when network connectivity was
lost. The throttling that was in place only took effect when the table
returned zero results, which doesn't happen very often.

The new throttling should not have a negative impact when the host is
online. Lookups against the network take some time and dials for all
results must complete or hit the cache before a new one is started. This
usually takes longer than four seconds, leaving online lookups
unaffected.

Fixes #1296
release/0.9.36
Felix Lange 10 years ago
parent 3deded28a5
commit 6fb810adaa
  1. 26
      p2p/dial.go
  2. 1
      p2p/server.go

@ -17,10 +17,9 @@ const (
// redialing a certain node. // redialing a certain node.
dialHistoryExpiration = 30 * time.Second dialHistoryExpiration = 30 * time.Second
// Discovery lookup tasks will wait for this long when // Discovery lookups are throttled and can only run
// no results are returned. This can happen if the table // once every few seconds.
// becomes empty (i.e. not often). lookupInterval = 4 * time.Second
emptyLookupDelay = 10 * time.Second
) )
// dialstate schedules dials and discovery lookups. // dialstate schedules dials and discovery lookups.
@ -206,18 +205,19 @@ func (t *dialTask) String() string {
func (t *discoverTask) Do(srv *Server) { func (t *discoverTask) Do(srv *Server) {
if t.bootstrap { if t.bootstrap {
srv.ntab.Bootstrap(srv.BootstrapNodes) srv.ntab.Bootstrap(srv.BootstrapNodes)
} else { return
var target discover.NodeID }
rand.Read(target[:])
t.results = srv.ntab.Lookup(target)
// newTasks generates a lookup task whenever dynamic dials are // newTasks generates a lookup task whenever dynamic dials are
// necessary. Lookups need to take some time, otherwise the // necessary. Lookups need to take some time, otherwise the
// event loop spins too fast. An empty result can only be // event loop spins too fast.
// returned if the table is empty. next := srv.lastLookup.Add(lookupInterval)
if len(t.results) == 0 { if now := time.Now(); now.Before(next) {
time.Sleep(emptyLookupDelay) time.Sleep(next.Sub(now))
}
} }
srv.lastLookup = time.Now()
var target discover.NodeID
rand.Read(target[:])
t.results = srv.ntab.Lookup(target)
} }
func (t *discoverTask) String() (s string) { func (t *discoverTask) String() (s string) {

@ -115,6 +115,7 @@ type Server struct {
ntab discoverTable ntab discoverTable
listener net.Listener listener net.Listener
ourHandshake *protoHandshake ourHandshake *protoHandshake
lastLookup time.Time
// These are for Peers, PeerCount (and nothing else). // These are for Peers, PeerCount (and nothing else).
peerOp chan peerOpFunc peerOp chan peerOpFunc

Loading…
Cancel
Save