Skip to content

Commit

Permalink
fix(libp2p): only dial one address at a time for peers (#2028)
Browse files Browse the repository at this point in the history
The observation for dialing is that for a given peer with multiple
addresses, for a given class of address (e.g. public or private),
either the first dial succeeds or they all fail, so there's not
much point dialing all addresses together since in either case you
waste resources either cancelling redundant dials or dialing addresses
that fail.

We can't do much about dialing addresses that fail but we can
reduce the number of redundant dials so with this change we only ever
dial one multiaddr at a time.
  • Loading branch information
achingbrain committed Sep 8, 2023
1 parent 46dc3ce commit 73b87c5
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 40 deletions.
14 changes: 7 additions & 7 deletions packages/libp2p/src/connection-manager/constants.browser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
export * from './constants.defaults.js'

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDials
*/
export const MAX_PARALLEL_DIALS = 10

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#minConnections
*/
Expand All @@ -16,6 +11,11 @@ export const MIN_CONNECTIONS = 5
export const MAX_CONNECTIONS = 100

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialConcurrency
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDials
*/
export const MAX_PARALLEL_DIALS = 50

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.unknown.ConnectionManagerInit.html#autoDialPeerRetryThreshold
*/
export const AUTO_DIAL_CONCURRENCY = 10
export const AUTO_DIAL_PEER_RETRY_THRESHOLD = 1000 * 60 * 7
12 changes: 6 additions & 6 deletions packages/libp2p/src/connection-manager/constants.defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ export const MAX_PEER_ADDRS_TO_DIAL = 25
/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDialsPerPeer
*/
export const MAX_PARALLEL_DIALS_PER_PEER = 10
export const MAX_PARALLEL_DIALS_PER_PEER = 1

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialInterval
*/
export const AUTO_DIAL_INTERVAL = 5000

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialConcurrency
*/
export const AUTO_DIAL_CONCURRENCY = 25

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialPriority
*/
Expand All @@ -33,11 +38,6 @@ export const AUTO_DIAL_PRIORITY = 0
*/
export const AUTO_DIAL_MAX_QUEUE_LENGTH = 100

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.unknown.ConnectionManagerInit.html#autoDialPeerRetryThreshold
*/
export const AUTO_DIAL_PEER_RETRY_THRESHOLD = 1000 * 60

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.unknown.ConnectionManagerInit.html#autoDialDiscoveredPeersDebounce
*/
Expand Down
14 changes: 7 additions & 7 deletions packages/libp2p/src/connection-manager/constants.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
export * from './constants.defaults.js'

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDials
*/
export const MAX_PARALLEL_DIALS = 100

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#minConnections
*/
Expand All @@ -16,6 +11,11 @@ export const MIN_CONNECTIONS = 50
export const MAX_CONNECTIONS = 300

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialConcurrency
* @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDials
*/
export const MAX_PARALLEL_DIALS = 100

/**
* @see https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.unknown.ConnectionManagerInit.html#autoDialPeerRetryThreshold
*/
export const AUTO_DIAL_CONCURRENCY = 25
export const AUTO_DIAL_PEER_RETRY_THRESHOLD = 1000 * 60
13 changes: 7 additions & 6 deletions packages/libp2p/src/connection-manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { codes } from '../errors.js'
import { getPeerAddress } from '../get-peer.js'
import { AutoDial } from './auto-dial.js'
import { ConnectionPruner } from './connection-pruner.js'
import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js'
import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PARALLEL_DIALS_PER_PEER, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js'
import { DialQueue } from './dial-queue.js'
import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions } from '@libp2p/interface'
import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection'
Expand All @@ -30,14 +30,14 @@ const DEFAULT_DIAL_PRIORITY = 50
export interface ConnectionManagerInit {
/**
* The maximum number of connections libp2p is willing to have before it starts
* pruning connections to reduce resource usage. (default: 300)
* pruning connections to reduce resource usage. (default: 300, 100 in browsers)
*/
maxConnections?: number

/**
* The minimum number of connections below which libp2p will start to dial peers
* from the peer book. Setting this to 0 effectively disables this behaviour.
* (default: 50)
* (default: 50, 5 in browsers)
*/
minConnections?: number

Expand Down Expand Up @@ -68,7 +68,7 @@ export interface ConnectionManagerInit {

/**
* When we've failed to dial a peer, do not autodial them again within this
* number of ms. (default: 1 minute)
* number of ms. (default: 1 minute, 7 minutes in browsers)
*/
autoDialPeerRetryThreshold?: number

Expand All @@ -88,15 +88,15 @@ export interface ConnectionManagerInit {

/**
* The maximum number of dials across all peers to execute in parallel.
* (default: 100)
* (default: 100, 50 in browsers)
*/
maxParallelDials?: number

/**
* To prevent individual peers with large amounts of multiaddrs swamping the
* dial queue, this value controls how many addresses to dial in parallel per
* peer. So for example if two peers have 10 addresses and this value is set
* at 5, we will dial 5 addresses from each at a time. (default: 10)
* at 5, we will dial 5 addresses from each at a time. (default: 1)
*/
maxParallelDialsPerPeer?: number

Expand Down Expand Up @@ -257,6 +257,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
addressSorter: init.addressSorter ?? publicAddressesFirst,
maxParallelDials: init.maxParallelDials ?? MAX_PARALLEL_DIALS,
maxPeerAddrsToDial: init.maxPeerAddrsToDial ?? MAX_PEER_ADDRS_TO_DIAL,
maxParallelDialsPerPeer: init.maxParallelDialsPerPeer ?? MAX_PARALLEL_DIALS_PER_PEER,
dialTimeout: init.dialTimeout ?? DIAL_TIMEOUT,
resolvers: init.resolvers ?? {
dnsaddr: dnsaddrResolver
Expand Down
10 changes: 2 additions & 8 deletions packages/libp2p/test/circuit-relay/relay.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,17 +470,11 @@ describe('circuit-relay', () => {

it('should not add listener to a already relayed connection', async () => {
// Relay 1 discovers Relay 3 and connect
await relay1.peerStore.merge(relay3.peerId, {
multiaddrs: relay3.getMultiaddrs()
})
await relay1.dial(relay3.peerId)
await relay1.dial(relay3.getMultiaddrs())
await usingAsRelay(relay1, relay3)

// Relay 2 discovers Relay 3 and connect
await relay2.peerStore.merge(relay3.peerId, {
multiaddrs: relay3.getMultiaddrs()
})
await relay2.dial(relay3.peerId)
await relay2.dial(relay3.getMultiaddrs())
await usingAsRelay(relay2, relay3)

// Relay 1 discovers Relay 2 relayed multiaddr via Relay 3
Expand Down
6 changes: 4 additions & 2 deletions packages/libp2p/test/connection-manager/dial-queue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ describe('dial queue', () => {
const controller = new AbortController()

dialer = new DialQueue(components, {
maxParallelDials: 2
maxParallelDials: 2,
maxParallelDialsPerPeer: 10
})

components.transportManager.transportForMultiaddr.returns(stubInterface<Transport>())
Expand Down Expand Up @@ -268,7 +269,8 @@ describe('dial queue', () => {
})

dialer = new DialQueue(components, {
maxParallelDials: 50
maxParallelDials: 50,
maxParallelDialsPerPeer: 10
})

await expect(dialer.dial(Object.keys(actions).map(str => multiaddr(str)))).to.eventually.equal(connection2)
Expand Down
7 changes: 5 additions & 2 deletions packages/libp2p/test/connection-manager/direct.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ describe('dialing (direct, TCP)', () => {
]

const dialer = new DialQueue(localComponents, {
maxParallelDials: 2
maxParallelDials: 2,
maxParallelDialsPerPeer: 10
})

const deferredDial = pDefer<Connection>()
Expand Down Expand Up @@ -268,7 +269,9 @@ describe('dialing (direct, TCP)', () => {
multiaddrs: addrs
})

const dialer = new DialQueue(localComponents)
const dialer = new DialQueue(localComponents, {
maxParallelDialsPerPeer: 10
})

const transportManagerDialStub = sinon.stub(localTM, 'dial')
transportManagerDialStub.callsFake(async (ma) => {
Expand Down
7 changes: 5 additions & 2 deletions packages/libp2p/test/connection-manager/direct.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ describe('dialing (direct, WebSockets)', () => {

connectionManager = new DefaultConnectionManager(localComponents, {
addressSorter: publicAddressesFirstSpy,
maxParallelDials: 3
maxParallelDials: 3,
maxParallelDialsPerPeer: 3
})
await connectionManager.start()

Expand Down Expand Up @@ -272,7 +273,9 @@ describe('dialing (direct, WebSockets)', () => {
multiaddrs: addrs
})

connectionManager = new DefaultConnectionManager(localComponents)
connectionManager = new DefaultConnectionManager(localComponents, {
maxParallelDialsPerPeer: 10
})
await connectionManager.start()

const transactionManagerDialStub = sinon.stub(localTM, 'dial')
Expand Down

0 comments on commit 73b87c5

Please sign in to comment.