Skip to content

Commit ff08648

Browse files
committed
Fix: Added more tests, fixed some bugs
1 parent 7dc8f29 commit ff08648

File tree

14 files changed

+514
-500
lines changed

14 files changed

+514
-500
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@
3333

3434
build
3535
CMakeUserPresets.json
36-
.vscode
36+
.vscode
37+
tests/functional/__pycache__
38+
Testing

configs/config.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,7 @@ load_balancing:
2626

2727

2828
# Example config of least connections
29-
algorithm: least_connections
30-
endpoints:
31-
- ip: "127.0.0.1"
32-
port: 8081
33-
- ip: "127.0.0.2"
34-
port: 8082
35-
- ip: "127.0.0.3"
36-
port: 8083
37-
38-
# Example config of least response time
39-
# algorithm: least_response_time
29+
# algorithm: least_connections
4030
# endpoints:
4131
# - ip: "127.0.0.1"
4232
# port: 8081
@@ -45,6 +35,16 @@ load_balancing:
4535
# - ip: "127.0.0.3"
4636
# port: 8083
4737

38+
# Example config of least response time
39+
algorithm: least_response_time
40+
endpoints:
41+
- ip: "127.0.0.1"
42+
port: 8081
43+
- ip: "127.0.0.2"
44+
port: 8082
45+
- ip: "127.0.0.3"
46+
port: 8083
47+
4848
# Example config of round robin
4949
# algorithm: round_robin
5050
# endpoints:

lbbuild.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function BuildApp() {
99
conan install . --output-folder=build --build=missing --settings=build_type=$BUILD_TYPE
1010
cd build
1111
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
12-
cmake --build . -j 4
12+
cmake --build . -j 3
1313
}
1414

1515
if ! command -v conan &> /dev/null

src/lb/formatters.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ namespace YAML {class Node;}
1010
template <> struct fmt::formatter<boost::stacktrace::stacktrace> : ostream_formatter{};
1111
template <> struct fmt::formatter<YAML::Node> : ostream_formatter{};
1212
template <> struct fmt::formatter<lb::tcp::Backend> : ostream_formatter{};
13-
template <> struct fmt::formatter<boost::beast::http::request<boost::beast::http::string_body>> : ostream_formatter{};
13+
template <> struct fmt::formatter<boost::beast::http::request<boost::beast::http::string_body>> : ostream_formatter{};
14+
template <> struct fmt::formatter<boost::beast::http::response<boost::beast::http::string_body>> : ostream_formatter{};

src/lb/tcp/connector.cpp

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <lb/tcp/connector.hpp>
33
#include <lb/tcp/session.hpp>
44

5+
using SocketType = lb::tcp::HttpSession::SocketType;
6+
57
namespace lb::tcp {
68

79
Connector::Connector(boost::asio::io_context& ctx, SelectorPtr selector)
@@ -10,38 +12,100 @@ Connector::Connector(boost::asio::io_context& ctx, SelectorPtr selector)
1012
, selector(selector)
1113
{}
1214

13-
SessionPtr MakeSession(SelectorPtr& selector, boost::asio::ip::tcp::socket client_socket, boost::asio::ip::tcp::socket server_socket, Backend backend)
15+
16+
class LeastConnectionsCallbacks : public StateNotifier
17+
{
18+
public:
19+
LeastConnectionsCallbacks(Backend backend, SelectorPtr selector)
20+
: StateNotifier()
21+
, backend(std::move(backend))
22+
, selector(std::dynamic_pointer_cast<LeastConnectionsSelector>(selector))
23+
{}
24+
25+
void OnConnect() override
26+
{
27+
selector->IncreaseConnectionCount(backend);
28+
}
29+
30+
void OnDisconnect() override
31+
{
32+
selector->DecreaseConnectionCount(backend);
33+
}
34+
35+
using StateNotifier::StateNotifier;
36+
private:
37+
Backend backend;
38+
std::shared_ptr<LeastConnectionsSelector> selector;
39+
};
40+
41+
42+
class LeastResponseTimeCallbacks : public StateNotifier
1443
{
44+
public:
45+
using TimeType = decltype(std::chrono::high_resolution_clock::now());
46+
public:
47+
LeastResponseTimeCallbacks(Backend backend, SelectorPtr selector)
48+
: StateNotifier()
49+
, backend(std::move(backend))
50+
, selector(std::dynamic_pointer_cast<LeastResponseTimeSelector>(selector))
51+
{}
52+
53+
void OnRequestSent() override
54+
{
55+
response_begin = std::chrono::high_resolution_clock::now();
56+
}
1557

16-
switch(selector->Type()) {
17-
case SelectorType::LEAST_CONNECTIONS: {
18-
std::shared_ptr<LeastConnectionsSelector> lc_selector = std::dynamic_pointer_cast<LeastConnectionsSelector>(selector);
19-
return std::make_shared<LeastConnectionsHttpSession>(std::move(client_socket), std::move(server_socket), lc_selector, backend);
20-
} break;
21-
case SelectorType::LEAST_RESPONSE_TIME: {
22-
std::shared_ptr<LeastResponseTimeSelector> lrt_selector = std::dynamic_pointer_cast<LeastResponseTimeSelector>(selector);
23-
return std::make_shared<LeastResponseTimeHttpSession>(std::move(client_socket), std::move(server_socket), lrt_selector, backend);
24-
} break;
25-
default: {
26-
return std::make_shared<HttpSession>(std::move(client_socket), std::move(server_socket));
27-
}
58+
void OnResponseReceive() override
59+
{
60+
response_end = std::chrono::high_resolution_clock::now();
61+
std::chrono::duration<long, std::nano> duration = response_end - response_begin;
62+
selector->AddResponseTime(backend, duration.count());
63+
}
64+
65+
using StateNotifier::StateNotifier;
66+
private:
67+
Backend backend;
68+
std::shared_ptr<LeastResponseTimeSelector> selector;
69+
TimeType response_begin;
70+
TimeType response_end;
71+
};
72+
73+
SessionPtr MakeSession(SelectorPtr& selector,
74+
SocketType client_socket,
75+
SocketType server_socket,
76+
Backend backend)
77+
{
78+
switch (selector->Type()) {
79+
case SelectorType::LEAST_CONNECTIONS:
80+
{
81+
return std::make_shared<HttpSession>(std::move(client_socket), std::move(server_socket),
82+
std::make_unique<LeastConnectionsCallbacks>(std::move(backend), selector));
83+
} break;
84+
85+
case SelectorType::LEAST_RESPONSE_TIME:
86+
{
87+
return std::make_shared<HttpSession>(std::move(client_socket), std::move(server_socket),
88+
std::make_unique<LeastResponseTimeCallbacks>(std::move(backend), selector));
89+
} break;
90+
default:
91+
return std::make_shared<HttpSession>(std::move(client_socket), std::move(server_socket));
2892
}
2993
}
3094

3195

32-
void Connector::MakeAndRunSession(boost::asio::ip::tcp::socket client_socket)
96+
void Connector::MakeAndRunSession(SocketType client_socket)
3397
{
34-
// TODO: selection of backend
3598
DEBUG("In connector");
3699
Backend backend = selector->SelectBackend(client_socket.remote_endpoint());
37100

38101
if (backend.IsIpEndpoint()) {
39102
DEBUG("Is ip endpoint");
40-
auto server_socket = std::make_shared<boost::asio::ip::tcp::socket>(client_socket.get_executor());
103+
auto server_socket = std::make_shared<SocketType>(client_socket.get_executor());
41104

42105
server_socket->async_connect(
43106
backend.AsEndpoint(),
44-
[this, server_socket, client_socket=std::move(client_socket), backend=std::move(backend)] (const boost::system::error_code& error) mutable
107+
[this, server_socket, client_socket=std::move(client_socket), backend=std::move(backend)]
108+
(const boost::system::error_code& error) mutable
45109
{
46110
if (error) {
47111
ERROR("{}", error.message());
@@ -56,7 +120,7 @@ void Connector::MakeAndRunSession(boost::asio::ip::tcp::socket client_socket)
56120
});
57121
} else if (backend.IsUrl()) {
58122
DEBUG("Is url");
59-
auto server_socket = std::make_shared<boost::asio::ip::tcp::socket>(client_socket.get_executor());
123+
auto server_socket = std::make_shared<SocketType>(client_socket.get_executor());
60124

61125
const auto& url = backend.AsUrl();
62126
DEBUG("URL: hostname: {}, port: {}", url.Hostname(), url.Port());

src/lb/tcp/connector.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ class Connector {
2121
Connector& operator=(Connector&&) = delete;
2222

2323
void MakeAndRunSession(boost::asio::ip::tcp::socket client);
24-
private:
25-
void HandleAsyncResolve(const boost::system::error_code& ec, ResolverResults results, boost::asio::ip::tcp::socket client_socket);
24+
2625
private:
2726
boost::asio::io_context& ioc;
2827
boost::asio::ip::tcp::resolver resolver;

src/lb/tcp/selectors.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ SelectorPtr DetectSelector(const YAML::Node& node)
152152
// ============================ RoundRobinSelector ============================
153153
void RoundRobinSelector::Configure(const YAML::Node &balancing_node)
154154
{
155+
INFO("Configuring RoundRobinSelector");
155156
if (!balancing_node["endpoints"].IsDefined()) {
156157
STACKTRACE("Round-robin endpoints node is missed");
157158
}
@@ -219,6 +220,7 @@ std::size_t ReadWeight(const YAML::Node& ep)
219220

220221
void WeightedRoundRobinSelector::Configure(const YAML::Node &balancing_node)
221222
{
223+
INFO("Configuring WeightedRoundRobinSelector");
222224
if (!balancing_node["endpoints"].IsDefined()) {
223225
STACKTRACE("Weighted-round-robin endpoints node is missed");
224226
}
@@ -314,6 +316,7 @@ void WeightedRoundRobinSelector::AdvanceCounter()
314316

315317
void IpHashSelector::Configure(const YAML::Node& balancing_node)
316318
{
319+
INFO("Configuring IpHashSelector");
317320
if (!balancing_node["endpoints"].IsDefined()) {
318321
STACKTRACE("Ip-hash endpoints node is missed");
319322
}
@@ -375,7 +378,10 @@ SelectorType IpHashSelector::Type() const
375378

376379
BackendCHTraits::HashType BackendCHTraits::GetHash(const Backend& backend)
377380
{
378-
return std::hash<std::string>{}(backend.ToString());
381+
382+
static std::hash<std::string> hash{};
383+
std::size_t res = hash(backend.ToString());
384+
return res;
379385
}
380386

381387
std::vector<BackendCHTraits::HashType>
@@ -398,6 +404,7 @@ ConsistentHashSelector::ConsistentHashSelector(std::size_t spawn_replicas)
398404

399405
void ConsistentHashSelector::Configure(const YAML::Node &balancing_node)
400406
{
407+
INFO("Configuring ConsistentHashSelector");
401408
if (!balancing_node["endpoints"].IsDefined()) {
402409
STACKTRACE("Consistent hash endpoints node is missed");
403410
}
@@ -429,13 +436,15 @@ Backend ConsistentHashSelector::SelectBackend(const boost::asio::ip::tcp::endpoi
429436
{
430437
boost::mutex::scoped_lock lock(mutex_);
431438
Backend result = ring_.SelectNode(client);
439+
DEBUG("Selected: {}", result);
432440
return result;
433441
}
434442

435443
void ConsistentHashSelector::ExcludeBackend(const Backend& backend)
436444
{
437445
boost::mutex::scoped_lock lock(mutex_);
438446
ring_.EraseNode(backend);
447+
DEBUG("Excluded: {}", backend);
439448
if (ring_.Empty()) {
440449
EXCEPTION("All backends are excluded!");
441450
}
@@ -449,6 +458,7 @@ SelectorType ConsistentHashSelector::Type() const
449458
// ============================ LeastConnectionsSelector ============================
450459

451460
void LeastConnectionsSelector::Configure(const YAML::Node& config) {
461+
INFO("Configuring LeastConnectionsSelector");
452462
if (!config["endpoints"].IsDefined()) {
453463
STACKTRACE("Least connections endpoints node is missed");
454464
}
@@ -546,6 +556,7 @@ void LeastConnectionsSelector::DecreaseConnectionCount(const Backend& backend)
546556

547557
void LeastResponseTimeSelector::Configure(const YAML::Node& config)
548558
{
559+
INFO("Configuring LeastResponseTimeSelector");
549560
if (!config["endpoints"].IsDefined()) {
550561
STACKTRACE("Least response time endpoints node is missed");
551562
}

0 commit comments

Comments
 (0)