From 9d119d264f8c1e2f76f0d15d6d13f004c9c5d4e7 Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 11:16:14 -0700 Subject: [PATCH 1/7] Make simulation test for load balancing. --- test/CMakeLists.txt | 1 + .../upstream/load_balancer_simulation_test.cc | 129 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 test/common/upstream/load_balancer_simulation_test.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1cab2bfd5ad2..a6d9a00b9a86 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -84,6 +84,7 @@ add_executable(envoy-test common/upstream/health_checker_impl_test.cc common/upstream/host_utility_test.cc common/upstream/load_balancer_impl_test.cc + common/upstream/load_balancer_simulation_test.cc common/upstream/logical_dns_cluster_test.cc common/upstream/resource_manager_impl_test.cc common/upstream/sds_test.cc diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc new file mode 100644 index 000000000000..3f50e4ca7425 --- /dev/null +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -0,0 +1,129 @@ +#include "common/runtime/runtime_impl.h" +#include "common/upstream/load_balancer_impl.h" +#include "common/upstream/upstream_impl.h" + +#include "test/mocks/runtime/mocks.h" +#include "test/mocks/upstream/mocks.h" + +using testing::NiceMock; +using testing::Return; + +namespace Upstream { + +static HostPtr newTestHost(const Upstream::Cluster& cluster, const std::string& url, + uint32_t weight = 1, const std::string& zone = "") { + return HostPtr{new HostImpl(cluster, url, false, weight, zone)}; +} + +/** + * This test is for simulation only and should not be run as part of unit tests. + */ +class DISABLED_SimulationTest : public testing::Test { +public: + DISABLED_SimulationTest() : stats_(ClusterImplBase::generateStats("", stats_store_)) {} + + /** + * @param originating_cluster total number of hosts in each zone in originating cluster. + * @param all_destination_cluster total number of all hosts in each zone in upstream cluster. + * @param healthy_destination_cluster total number of healthy hosts in each zone in upstream + * cluster. + */ + void run(std::vector originating_cluster, std::vector all_destination_cluster, + std::vector healthy_destination_cluster) { + setupRuntime(); + stats_.upstream_zone_count_.set(all_destination_cluster.size()); + + // zone to list of healthy hosts + std::unordered_map> healthy_map = + generateMap(healthy_destination_cluster); + std::unordered_map> all_map = + generateMap(all_destination_cluster); + + std::vector originatingHosts = generateList(originating_cluster); + cluster_.healthy_hosts_ = generateList(healthy_destination_cluster); + cluster_.hosts_ = generateList(all_destination_cluster); + + std::map hits; + for (uint32_t i = 0; i < total_number_of_requests; ++i) { + HostPtr from_host = selectOriginatingHost(originatingHosts); + + cluster_.local_zone_hosts_ = all_map[from_host->zone()]; + cluster_.local_zone_healthy_hosts_ = healthy_map[from_host->zone()]; + + ConstHostPtr selected = lb_.chooseHost(); + hits[selected->url()]++; + } + + for (auto& host_hit_num_pair : hits) { + std::cout << fmt::format("url:{}, hits:{}", host_hit_num_pair.first, host_hit_num_pair.second) + << std::endl; + } + } + + HostPtr selectOriginatingHost(const std::vector& hosts) { + // Originating cluster should have roughly the same per host request distribution. + return hosts[random_.random() % hosts.size()]; + } + + std::vector generateList(const std::vector& hosts) { + std::vector ret; + for (size_t i = 0; i < hosts.size(); ++i) { + const std::string zone = std::to_string(i); + for (uint32_t j = 0; j < hosts[i]; ++j) { + // url:zone:host_number + const std::string url = fmt::format("tcp://host.{}.{}:80", i, j); + ret.push_back(newTestHost(cluster_, url, 1, zone)); + } + } + + return ret; + } + + std::unordered_map> + generateMap(const std::vector& hosts) { + std::unordered_map> ret; + for (size_t i = 0; i < hosts.size(); ++i) { + const std::string zone = std::to_string(i); + std::vector zone_hosts; + + for (uint32_t j = 0; j < hosts[i]; ++j) { + // url:zone:host_number + const std::string url = fmt::format("tcp://host.{}.{}:80", i, j); + zone_hosts.push_back(newTestHost(cluster_, url, 1, zone)); + } + + ret.insert({zone, std::move(zone_hosts)}); + } + + return ret; + }; + + void setupRuntime() { + ON_CALL(runtime_.snapshot_, getInteger("upstream.healthy_panic_threshold", 50U)) + .WillByDefault(Return(50U)); + ON_CALL(runtime_.snapshot_, featureEnabled("upstream.zone_routing.enabled", 100)) + .WillByDefault(Return(true)); + ON_CALL(runtime_.snapshot_, getInteger("upstream.zone_routing.percent_diff", 3)) + .WillByDefault(Return(3)); + } + + const uint32_t total_number_of_requests = 100000; + + NiceMock cluster_; + NiceMock runtime_; + Runtime::RandomGeneratorImpl random_; + Stats::IsolatedStoreImpl stats_store_; + ClusterStats stats_; + // TODO: make per originating host load balancer. + RandomLoadBalancer lb_{cluster_, stats_, runtime_, random_}; +}; + +TEST_F(DISABLED_SimulationTest, strictlyEqualDistribution) { + run({1U, 1U, 1U}, {3U, 3U, 3U}, {3U, 3U, 3U}); +} + +TEST_F(DISABLED_SimulationTest, unequalZoneDistribution) { + run({1U, 1U, 1U}, {5U, 5U, 6U}, {5U, 5U, 6U}); +} + +} // Upstream \ No newline at end of file From a369c32fab5aee5420d387584a2b3e48a6465a4d Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 11:30:34 -0700 Subject: [PATCH 2/7] comment changes. --- test/common/upstream/load_balancer_simulation_test.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index 3f50e4ca7425..90524151e767 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -24,7 +24,7 @@ class DISABLED_SimulationTest : public testing::Test { /** * @param originating_cluster total number of hosts in each zone in originating cluster. - * @param all_destination_cluster total number of all hosts in each zone in upstream cluster. + * @param all_destination_cluster total number of hosts in each zone in upstream cluster. * @param healthy_destination_cluster total number of healthy hosts in each zone in upstream * cluster. */ @@ -33,7 +33,6 @@ class DISABLED_SimulationTest : public testing::Test { setupRuntime(); stats_.upstream_zone_count_.set(all_destination_cluster.size()); - // zone to list of healthy hosts std::unordered_map> healthy_map = generateMap(healthy_destination_cluster); std::unordered_map> all_map = @@ -54,7 +53,7 @@ class DISABLED_SimulationTest : public testing::Test { hits[selected->url()]++; } - for (auto& host_hit_num_pair : hits) { + for (const auto& host_hit_num_pair : hits) { std::cout << fmt::format("url:{}, hits:{}", host_hit_num_pair.first, host_hit_num_pair.second) << std::endl; } @@ -70,7 +69,6 @@ class DISABLED_SimulationTest : public testing::Test { for (size_t i = 0; i < hosts.size(); ++i) { const std::string zone = std::to_string(i); for (uint32_t j = 0; j < hosts[i]; ++j) { - // url:zone:host_number const std::string url = fmt::format("tcp://host.{}.{}:80", i, j); ret.push_back(newTestHost(cluster_, url, 1, zone)); } From 58c34186ce01b9badbf7628d5d330eb62766d782 Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 11:31:56 -0700 Subject: [PATCH 3/7] comment removed. --- test/common/upstream/load_balancer_simulation_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index 90524151e767..d6bbfe106df7 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -85,7 +85,6 @@ class DISABLED_SimulationTest : public testing::Test { std::vector zone_hosts; for (uint32_t j = 0; j < hosts[i]; ++j) { - // url:zone:host_number const std::string url = fmt::format("tcp://host.{}.{}:80", i, j); zone_hosts.push_back(newTestHost(cluster_, url, 1, zone)); } From eb1469af45f6c43e047f7e142ef9acd65f007d1b Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 16:06:41 -0700 Subject: [PATCH 4/7] PR comments. --- .../upstream/load_balancer_simulation_test.cc | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index d6bbfe106df7..f0de5b22c19e 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -20,7 +20,9 @@ static HostPtr newTestHost(const Upstream::Cluster& cluster, const std::string& */ class DISABLED_SimulationTest : public testing::Test { public: - DISABLED_SimulationTest() : stats_(ClusterImplBase::generateStats("", stats_store_)) {} + DISABLED_SimulationTest() : stats_(ClusterImplBase::generateStats("", stats_store_)) { + setupRuntime(); + } /** * @param originating_cluster total number of hosts in each zone in originating cluster. @@ -30,21 +32,20 @@ class DISABLED_SimulationTest : public testing::Test { */ void run(std::vector originating_cluster, std::vector all_destination_cluster, std::vector healthy_destination_cluster) { - setupRuntime(); stats_.upstream_zone_count_.set(all_destination_cluster.size()); std::unordered_map> healthy_map = - generateMap(healthy_destination_cluster); + generateHostsPerZone(healthy_destination_cluster); std::unordered_map> all_map = - generateMap(all_destination_cluster); + generateHostsPerZone(all_destination_cluster); - std::vector originatingHosts = generateList(originating_cluster); - cluster_.healthy_hosts_ = generateList(healthy_destination_cluster); - cluster_.hosts_ = generateList(all_destination_cluster); + std::vector originating_hosts = generateHostList(originating_cluster); + cluster_.healthy_hosts_ = generateHostList(healthy_destination_cluster); + cluster_.hosts_ = generateHostList(all_destination_cluster); std::map hits; for (uint32_t i = 0; i < total_number_of_requests; ++i) { - HostPtr from_host = selectOriginatingHost(originatingHosts); + HostPtr from_host = selectOriginatingHost(originating_hosts); cluster_.local_zone_hosts_ = all_map[from_host->zone()]; cluster_.local_zone_healthy_hosts_ = healthy_map[from_host->zone()]; @@ -64,7 +65,11 @@ class DISABLED_SimulationTest : public testing::Test { return hosts[random_.random() % hosts.size()]; } - std::vector generateList(const std::vector& hosts) { + /** + * Generate list of hosts based on number of hosts in the given zone. + * @param hosts number of hosts per zone. + */ + std::vector generateHostList(const std::vector &hosts) { std::vector ret; for (size_t i = 0; i < hosts.size(); ++i) { const std::string zone = std::to_string(i); @@ -77,8 +82,12 @@ class DISABLED_SimulationTest : public testing::Test { return ret; } + /** + * Generate hosts by zone. + * @param hosts number of hosts per zone. + */ std::unordered_map> - generateMap(const std::vector& hosts) { + generateHostsPerZone(const std::vector &hosts) { std::unordered_map> ret; for (size_t i = 0; i < hosts.size(); ++i) { const std::string zone = std::to_string(i); From d11aa7a0632e1ead68c5b66e25c704f59143850e Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 16:07:58 -0700 Subject: [PATCH 5/7] comment on run method. --- test/common/upstream/load_balancer_simulation_test.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index f0de5b22c19e..6ff7283771a2 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -25,6 +25,8 @@ class DISABLED_SimulationTest : public testing::Test { } /** + * Run simulation with given parameters. Generate statistics on per host requests. + * * @param originating_cluster total number of hosts in each zone in originating cluster. * @param all_destination_cluster total number of hosts in each zone in upstream cluster. * @param healthy_destination_cluster total number of healthy hosts in each zone in upstream From da6d9a2681d0a7fcd9045244e0ae9806813f23ae Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Thu, 6 Oct 2016 16:13:07 -0700 Subject: [PATCH 6/7] Fix. --- test/common/upstream/load_balancer_simulation_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index 6ff7283771a2..b778cc8b41c4 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -37,9 +37,9 @@ class DISABLED_SimulationTest : public testing::Test { stats_.upstream_zone_count_.set(all_destination_cluster.size()); std::unordered_map> healthy_map = - generateHostsPerZone(healthy_destination_cluster); + generateHostsPerZone(healthy_destination_cluster); std::unordered_map> all_map = - generateHostsPerZone(all_destination_cluster); + generateHostsPerZone(all_destination_cluster); std::vector originating_hosts = generateHostList(originating_cluster); cluster_.healthy_hosts_ = generateHostList(healthy_destination_cluster); @@ -71,7 +71,7 @@ class DISABLED_SimulationTest : public testing::Test { * Generate list of hosts based on number of hosts in the given zone. * @param hosts number of hosts per zone. */ - std::vector generateHostList(const std::vector &hosts) { + std::vector generateHostList(const std::vector& hosts) { std::vector ret; for (size_t i = 0; i < hosts.size(); ++i) { const std::string zone = std::to_string(i); @@ -89,7 +89,7 @@ class DISABLED_SimulationTest : public testing::Test { * @param hosts number of hosts per zone. */ std::unordered_map> - generateHostsPerZone(const std::vector &hosts) { + generateHostsPerZone(const std::vector& hosts) { std::unordered_map> ret; for (size_t i = 0; i < hosts.size(); ++i) { const std::string zone = std::to_string(i); From f9897a19ff260420116a055fc52d0023ad6c1d97 Mon Sep 17 00:00:00 2001 From: Roman Dzhabarov Date: Fri, 7 Oct 2016 09:17:19 -0700 Subject: [PATCH 7/7] Remove setupRuntime. --- .../upstream/load_balancer_simulation_test.cc | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index b778cc8b41c4..0648312a2ffd 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -21,7 +21,12 @@ static HostPtr newTestHost(const Upstream::Cluster& cluster, const std::string& class DISABLED_SimulationTest : public testing::Test { public: DISABLED_SimulationTest() : stats_(ClusterImplBase::generateStats("", stats_store_)) { - setupRuntime(); + ON_CALL(runtime_.snapshot_, getInteger("upstream.healthy_panic_threshold", 50U)) + .WillByDefault(Return(50U)); + ON_CALL(runtime_.snapshot_, featureEnabled("upstream.zone_routing.enabled", 100)) + .WillByDefault(Return(true)); + ON_CALL(runtime_.snapshot_, getInteger("upstream.zone_routing.percent_diff", 3)) + .WillByDefault(Return(3)); } /** @@ -106,15 +111,6 @@ class DISABLED_SimulationTest : public testing::Test { return ret; }; - void setupRuntime() { - ON_CALL(runtime_.snapshot_, getInteger("upstream.healthy_panic_threshold", 50U)) - .WillByDefault(Return(50U)); - ON_CALL(runtime_.snapshot_, featureEnabled("upstream.zone_routing.enabled", 100)) - .WillByDefault(Return(true)); - ON_CALL(runtime_.snapshot_, getInteger("upstream.zone_routing.percent_diff", 3)) - .WillByDefault(Return(3)); - } - const uint32_t total_number_of_requests = 100000; NiceMock cluster_;