From 4faa4edeb49f59cefe002d1e780c4e804d147b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:11:16 +0100 Subject: [PATCH] Rate limit ascending bootstrap requests --- nano/node/bootstrap/bootstrap_config.cpp | 2 ++ nano/node/bootstrap/bootstrap_config.hpp | 3 ++- nano/node/bootstrap/bootstrap_service.cpp | 9 +++++++-- nano/node/bootstrap/bootstrap_service.hpp | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/nano/node/bootstrap/bootstrap_config.cpp b/nano/node/bootstrap/bootstrap_config.cpp index 94184871e3..47f0da94ec 100644 --- a/nano/node/bootstrap/bootstrap_config.cpp +++ b/nano/node/bootstrap/bootstrap_config.cpp @@ -36,6 +36,7 @@ nano::error nano::bootstrap_config::deserialize (nano::tomlconfig & toml) toml.get ("enable_dependency_walker", enable_dependency_walker); toml.get ("channel_limit", channel_limit); + toml.get ("rate_limit", rate_limit); toml.get ("database_rate_limit", database_rate_limit); toml.get ("database_warmup_ratio", database_warmup_ratio); toml.get ("max_pull_count", max_pull_count); @@ -62,6 +63,7 @@ nano::error nano::bootstrap_config::serialize (nano::tomlconfig & toml) const toml.put ("enable_dependency_walker", enable_dependency_walker, "Enable or disable the 'dependency walker` strategy.\ntype:bool"); toml.put ("channel_limit", channel_limit, "Maximum number of un-responded requests per channel.\nNote: changing to unlimited (0) is not recommended.\ntype:uint64"); + toml.put ("rate_limit", rate_limit, "Rate limit on requests.\nNote: changing to unlimited (0) is not recommended as this operation competes for resources with realtime traffic.\ntype:uint64"); toml.put ("database_rate_limit", database_rate_limit, "Rate limit on scanning accounts and pending entries from database.\nNote: changing to unlimited (0) is not recommended as this operation competes for resources on querying the database.\ntype:uint64"); toml.put ("database_warmup_ratio", database_warmup_ratio, "Ratio of the database rate limit to use for the initial warmup.\ntype:uint64"); toml.put ("max_pull_count", max_pull_count, "Maximum number of requested blocks for bootstrap request.\ntype:uint64"); diff --git a/nano/node/bootstrap/bootstrap_config.hpp b/nano/node/bootstrap/bootstrap_config.hpp index be5a288faa..bcf35258c1 100644 --- a/nano/node/bootstrap/bootstrap_config.hpp +++ b/nano/node/bootstrap/bootstrap_config.hpp @@ -34,7 +34,8 @@ class bootstrap_config final // Maximum number of un-responded requests per channel, should be lower or equal to bootstrap server max queue size std::size_t channel_limit{ 16 }; - std::size_t database_rate_limit{ 256 }; + std::size_t rate_limit{ 500 }; + std::size_t database_rate_limit{ 250 }; std::size_t database_warmup_ratio{ 10 }; std::size_t max_pull_count{ nano::bootstrap_server::max_blocks }; std::chrono::milliseconds request_timeout{ 1000 * 5 }; diff --git a/nano/node/bootstrap/bootstrap_service.cpp b/nano/node/bootstrap/bootstrap_service.cpp index 023b247beb..832ba160bc 100644 --- a/nano/node/bootstrap/bootstrap_service.cpp +++ b/nano/node/bootstrap/bootstrap_service.cpp @@ -28,6 +28,7 @@ nano::bootstrap_service::bootstrap_service (nano::node_config const & node_confi database_scan{ ledger }, throttle{ compute_throttle_size () }, scoring{ config, node_config_a.network_params.network }, + limiter{ config.rate_limit, 1.0 }, database_limiter{ config.database_rate_limit, 1.0 } { block_processor.batch_processed.add ([this] (auto const & batch) { @@ -257,7 +258,6 @@ void nano::bootstrap_service::wait (std::function const & predicate) co void nano::bootstrap_service::wait_tags () const { wait ([this] () { - debug_assert (!mutex.try_lock ()); return tags.size () < config.max_requests; }); } @@ -271,9 +271,14 @@ void nano::bootstrap_service::wait_blockprocessor () const std::shared_ptr nano::bootstrap_service::wait_channel () { + // Wait until more requests can be sent + wait ([this] () { + return !limiter.should_pass (1); + }); + + // Wait until a channel is available std::shared_ptr channel; wait ([this, &channel] () { - debug_assert (!mutex.try_lock ()); channel = scoring.channel (); return channel != nullptr; // Wait until a channel is available }); diff --git a/nano/node/bootstrap/bootstrap_service.hpp b/nano/node/bootstrap/bootstrap_service.hpp index 216c08d8e4..34ec7e4b9b 100644 --- a/nano/node/bootstrap/bootstrap_service.hpp +++ b/nano/node/bootstrap/bootstrap_service.hpp @@ -175,6 +175,8 @@ class bootstrap_service // clang-format on ordered_tags tags; + // Rate limiter for all types of requests + nano::rate_limiter limiter; // Requests for accounts from database have much lower hitrate and could introduce strain on the network // A separate (lower) limiter ensures that we always reserve resources for querying accounts from priority queue nano::rate_limiter database_limiter;