From 10c250a4822e0d0602fc5a436c0fda7273ec2fe2 Mon Sep 17 00:00:00 2001 From: Josh McAtee Date: Tue, 10 Jun 2025 09:10:27 -0700 Subject: [PATCH] Fix "load balancing" not working Before this commit, the load balancing does not work. The foundation is there, but in practice, the next connection is always picked. For example, if there are 3 contexts available, it will always go: 0, 1, 2, 0, 1, 2, 0, 1, 2, etc. If 0 is a long running connection, and 1 and 2 are short, it will pick 0 for the next connection and then block waiting for that long running connection to end even though 1 and 2 are free. With this fix, the above example would result in this sequence: 0, 1, 2, 1, 2, 1, 2, 1, 2 (until 0 is done with its long running connection). --- include/crow/http_connection.h | 2 ++ include/crow/http_server.h | 22 ++++++++-------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/crow/http_connection.h b/include/crow/http_connection.h index 857a37015b..146c737899 100644 --- a/include/crow/http_connection.h +++ b/include/crow/http_connection.h @@ -69,6 +69,7 @@ namespace crow res_stream_threshold_(handler->stream_threshold()), queue_length_(queue_length) { + queue_length_++; #ifdef CROW_ENABLE_DEBUG connectionCount++; CROW_LOG_DEBUG << "Connection (" << this << ") allocated, total: " << connectionCount; @@ -77,6 +78,7 @@ namespace crow ~Connection() { + queue_length_--; #ifdef CROW_ENABLE_DEBUG connectionCount--; CROW_LOG_DEBUG << "Connection (" << this << ") freed, total: " << connectionCount; diff --git a/include/crow/http_server.h b/include/crow/http_server.h index d364ba2d62..5eb116a2c4 100644 --- a/include/crow/http_server.h +++ b/include/crow/http_server.h @@ -49,14 +49,14 @@ namespace crow // NOTE: Already documented in "crow/app.h" uint16_t concurrency = 1, uint8_t timeout = 5, typename Adaptor::context* adaptor_ctx = nullptr): + concurrency_(concurrency), + task_queue_length_pool_(concurrency_ - 1), acceptor_(io_context_), signals_(io_context_), tick_timer_(io_context_), handler_(handler), - concurrency_(concurrency), timeout_(timeout), server_name_(server_name), - task_queue_length_pool_(concurrency_ - 1), middlewares_(middlewares), adaptor_ctx_(adaptor_ctx) { @@ -300,12 +300,11 @@ namespace crow // NOTE: Already documented in "crow/app.h" { uint16_t context_idx = pick_io_context_idx(); asio::io_context& ic = *io_context_pool_[context_idx]; - task_queue_length_pool_[context_idx]++; - CROW_LOG_DEBUG << &ic << " {" << context_idx << "} queue length: " << task_queue_length_pool_[context_idx]; - auto p = std::make_shared>( - ic, handler_, server_name_, middlewares_, - get_cached_date_str_pool_[context_idx], *task_timer_pool_[context_idx], adaptor_ctx_, task_queue_length_pool_[context_idx]); + ic, handler_, server_name_, middlewares_, + get_cached_date_str_pool_[context_idx], *task_timer_pool_[context_idx], adaptor_ctx_, task_queue_length_pool_[context_idx]); + + CROW_LOG_DEBUG << &ic << " {" << context_idx << "} queue length: " << task_queue_length_pool_[context_idx]; acceptor_.async_accept( p->socket(), @@ -317,11 +316,6 @@ namespace crow // NOTE: Already documented in "crow/app.h" p->start(); }); } - else - { - task_queue_length_pool_[context_idx]--; - CROW_LOG_DEBUG << &ic << " {" << context_idx << "} queue length: " << task_queue_length_pool_[context_idx]; - } do_accept(); }); } @@ -336,6 +330,8 @@ namespace crow // NOTE: Already documented in "crow/app.h" } private: + uint16_t concurrency_{2}; + std::vector> task_queue_length_pool_; std::vector> io_context_pool_; asio::io_context io_context_; std::vector task_timer_pool_; @@ -351,10 +347,8 @@ namespace crow // NOTE: Already documented in "crow/app.h" asio::basic_waitable_timer tick_timer_; Handler* handler_; - uint16_t concurrency_{2}; std::uint8_t timeout_; std::string server_name_; - std::vector> task_queue_length_pool_; std::chrono::milliseconds tick_interval_; std::function tick_function_;