add connection limits configuration and logging for max concurrent peers

This commit is contained in:
cloudwithax 2026-02-14 22:14:20 -05:00
parent 6ed6a1524e
commit 47af6658a2
1 changed files with 42 additions and 2 deletions

View File

@ -13,17 +13,24 @@
// RUST_LOG=info cargo run // RUST_LOG=info cargo run
// DUSK_RELAY_PORT=4001 cargo run (custom port) // DUSK_RELAY_PORT=4001 cargo run (custom port)
// DUSK_PEER_RELAYS="addr1,addr2" cargo run (federation) // DUSK_PEER_RELAYS="addr1,addr2" cargo run (federation)
// DUSK_MAX_CONNECTIONS=10000 cargo run (connection limit, default 10k)
// //
// canonical public relay (default in dusk chat clients): // canonical public relay (default in dusk chat clients):
// /dns4/relay.duskchat.app/tcp/4001/p2p/12D3KooWGQkCkACcibJPKzus7Q6U1aYngfTuS4gwYwmJkJJtrSaw // /dns4/relay.duskchat.app/tcp/4001/p2p/12D3KooWGQkCkACcibJPKzus7Q6U1aYngfTuS4gwYwmJkJJtrSaw
//
// recommended connection limits by instance size:
// t3.small (2GB): 5,000 max connections
// t3.medium (4GB): 10,000 max connections (default)
// t3.large (8GB): 20,000 max connections
// c6i.xlarge: 50,000 max connections (with kernel tuning)
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use futures::StreamExt; use futures::StreamExt;
use libp2p::{ use libp2p::{
gossipsub, identify, noise, ping, relay, rendezvous, swarm::SwarmEvent, tcp, yamux, Multiaddr, connection_limits, gossipsub, identify, noise, ping, relay, rendezvous, swarm::SwarmEvent,
PeerId, tcp, yamux, Multiaddr, PeerId,
}; };
// gossip message for relay-to-relay federation // gossip message for relay-to-relay federation
@ -45,6 +52,7 @@ struct RelayBehaviour {
gossipsub: gossipsub::Behaviour, gossipsub: gossipsub::Behaviour,
identify: identify::Behaviour, identify: identify::Behaviour,
ping: ping::Behaviour, ping: ping::Behaviour,
limits: connection_limits::Behaviour,
} }
// resolve the path where we persist the relay's keypair so the peer id is stable // resolve the path where we persist the relay's keypair so the peer id is stable
@ -95,6 +103,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.and_then(|p| p.parse().ok()) .and_then(|p| p.parse().ok())
.unwrap_or(4001); .unwrap_or(4001);
// max concurrent peer connections (not including peer relay connections)
// default 10k, configurable via env var for different instance sizes
let max_connections: u32 = std::env::var("DUSK_MAX_CONNECTIONS")
.ok()
.and_then(|c| c.parse().ok())
.unwrap_or(10_000);
log::info!("connection limit: {} max concurrent peers", max_connections);
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(keypair.clone()) let mut swarm = libp2p::SwarmBuilder::with_existing_identity(keypair.clone())
.with_tokio() .with_tokio()
.with_tcp( .with_tcp(
@ -124,6 +141,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
) )
.expect("valid gossipsub behaviour"); .expect("valid gossipsub behaviour");
// read connection limit (max total concurrent connections across all peers)
let max_connections = std::env::var("DUSK_MAX_CONNECTIONS")
.ok()
.and_then(|c| c.parse().ok())
.unwrap_or(10_000);
RelayBehaviour { RelayBehaviour {
relay: relay::Behaviour::new(peer_id, relay::Config::default()), relay: relay::Behaviour::new(peer_id, relay::Config::default()),
rendezvous: rendezvous::server::Behaviour::new( rendezvous: rendezvous::server::Behaviour::new(
@ -136,6 +159,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
)), )),
// ping every 30s to keep peer connections alive // ping every 30s to keep peer connections alive
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(30))), ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(30))),
// limit total concurrent connections (default 10k for ~t3.medium)
limits: connection_limits::Behaviour::new(
connection_limits::ConnectionLimits::default()
.with_max_established(Some(max_connections))
),
} }
})? })?
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(300))) .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(300)))
@ -359,6 +387,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
// connection limit events
SwarmEvent::IncomingConnectionError { error, .. } => {
if let libp2p::swarm::ListenError::Denied { cause } = error {
if cause.to_string().contains("connection limit") {
log::warn!(
"connection rejected: relay at capacity ({} max connections)",
max_connections
);
}
}
}
// identify events - log protocol info from connecting peers // identify events - log protocol info from connecting peers
SwarmEvent::Behaviour(RelayBehaviourEvent::Identify( SwarmEvent::Behaviour(RelayBehaviourEvent::Identify(
identify::Event::Received { peer_id, info, .. }, identify::Event::Received { peer_id, info, .. },