|
11 | 11 | #include "envoy/config/core/v3/base.pb.h" |
12 | 12 | #include "envoy/config/core/v3/health_check.pb.h" |
13 | 13 |
|
| 14 | +#include "source/common/common/random_generator.h" |
14 | 15 | #include "source/common/network/utility.h" |
15 | 16 | #include "source/common/upstream/load_balancer_impl.h" |
16 | 17 | #include "source/common/upstream/upstream_impl.h" |
@@ -2880,6 +2881,96 @@ TEST_P(LeastRequestLoadBalancerTest, PNC) { |
2880 | 2881 | EXPECT_EQ(hostSet().healthy_hosts_[3], lb_5.chooseHost(nullptr)); |
2881 | 2882 | } |
2882 | 2883 |
|
| 2884 | +TEST_P(LeastRequestLoadBalancerTest, DefaultSelectionMethod) { |
| 2885 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest lr_lb_config; |
| 2886 | + EXPECT_EQ(lr_lb_config.selection_method(), |
| 2887 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::N_CHOICES); |
| 2888 | +} |
| 2889 | + |
| 2890 | +TEST_P(LeastRequestLoadBalancerTest, FullScanOneHostWithLeastRequests) { |
| 2891 | + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime()), |
| 2892 | + makeTestHost(info_, "tcp://127.0.0.1:81", simTime()), |
| 2893 | + makeTestHost(info_, "tcp://127.0.0.1:82", simTime()), |
| 2894 | + makeTestHost(info_, "tcp://127.0.0.1:83", simTime()), |
| 2895 | + makeTestHost(info_, "tcp://127.0.0.1:84", simTime())}; |
| 2896 | + hostSet().hosts_ = hostSet().healthy_hosts_; |
| 2897 | + hostSet().runCallbacks({}, {}); // Trigger callbacks. The added/removed lists are not relevant. |
| 2898 | + |
| 2899 | + hostSet().healthy_hosts_[0]->stats().rq_active_.set(4); |
| 2900 | + hostSet().healthy_hosts_[1]->stats().rq_active_.set(3); |
| 2901 | + hostSet().healthy_hosts_[2]->stats().rq_active_.set(2); |
| 2902 | + hostSet().healthy_hosts_[3]->stats().rq_active_.set(1); |
| 2903 | + hostSet().healthy_hosts_[4]->stats().rq_active_.set(5); |
| 2904 | + |
| 2905 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest lr_lb_config; |
| 2906 | + |
| 2907 | + // Enable FULL_SCAN on hosts. |
| 2908 | + lr_lb_config.set_selection_method( |
| 2909 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::FULL_SCAN); |
| 2910 | + |
| 2911 | + LeastRequestLoadBalancer lb{priority_set_, nullptr, stats_, runtime_, |
| 2912 | + random_, 1, lr_lb_config, simTime()}; |
| 2913 | + |
| 2914 | + // With FULL_SCAN we will always choose the host with least number of active requests. |
| 2915 | + EXPECT_EQ(hostSet().healthy_hosts_[3], lb.chooseHost(nullptr)); |
| 2916 | +} |
| 2917 | + |
| 2918 | +TEST_P(LeastRequestLoadBalancerTest, FullScanMultipleHostsWithLeastRequests) { |
| 2919 | + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime()), |
| 2920 | + makeTestHost(info_, "tcp://127.0.0.1:81", simTime()), |
| 2921 | + makeTestHost(info_, "tcp://127.0.0.1:82", simTime()), |
| 2922 | + makeTestHost(info_, "tcp://127.0.0.1:83", simTime()), |
| 2923 | + makeTestHost(info_, "tcp://127.0.0.1:84", simTime())}; |
| 2924 | + hostSet().hosts_ = hostSet().healthy_hosts_; |
| 2925 | + hostSet().runCallbacks({}, {}); // Trigger callbacks. The added/removed lists are not relevant. |
| 2926 | + |
| 2927 | + hostSet().healthy_hosts_[0]->stats().rq_active_.set(3); |
| 2928 | + hostSet().healthy_hosts_[1]->stats().rq_active_.set(3); |
| 2929 | + hostSet().healthy_hosts_[2]->stats().rq_active_.set(1); |
| 2930 | + hostSet().healthy_hosts_[3]->stats().rq_active_.set(1); |
| 2931 | + hostSet().healthy_hosts_[4]->stats().rq_active_.set(1); |
| 2932 | + |
| 2933 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest lr_lb_config; |
| 2934 | + |
| 2935 | + // Enable FULL_SCAN on hosts. |
| 2936 | + lr_lb_config.set_selection_method( |
| 2937 | + envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest::FULL_SCAN); |
| 2938 | + |
| 2939 | + auto random = Random::RandomGeneratorImpl(); |
| 2940 | + |
| 2941 | + LeastRequestLoadBalancer lb{priority_set_, nullptr, stats_, runtime_, |
| 2942 | + random, 1, lr_lb_config, simTime()}; |
| 2943 | + |
| 2944 | + // Make 1 million selections. Then, check that the selection probability is |
| 2945 | + // approximately equal among the 3 hosts tied for least requests. |
| 2946 | + // Accept a +/-0.5% deviation from the expected selection probability (33.3..%). |
| 2947 | + size_t num_selections = 1000000; |
| 2948 | + size_t expected_approx_selections_per_tied_host = num_selections / 3; |
| 2949 | + size_t abs_error = 5000; |
| 2950 | + |
| 2951 | + size_t host_2_counts = 0; |
| 2952 | + size_t host_3_counts = 0; |
| 2953 | + size_t host_4_counts = 0; |
| 2954 | + |
| 2955 | + for (size_t i = 0; i < num_selections; ++i) { |
| 2956 | + auto selected_host = lb.chooseHost(nullptr); |
| 2957 | + |
| 2958 | + if (selected_host == hostSet().healthy_hosts_[2]) { |
| 2959 | + ++host_2_counts; |
| 2960 | + } else if (selected_host == hostSet().healthy_hosts_[3]) { |
| 2961 | + ++host_3_counts; |
| 2962 | + } else if (selected_host == hostSet().healthy_hosts_[4]) { |
| 2963 | + ++host_4_counts; |
| 2964 | + } else { |
| 2965 | + FAIL() << "Must only select hosts with least requests"; |
| 2966 | + } |
| 2967 | + } |
| 2968 | + |
| 2969 | + EXPECT_NEAR(expected_approx_selections_per_tied_host, host_2_counts, abs_error); |
| 2970 | + EXPECT_NEAR(expected_approx_selections_per_tied_host, host_3_counts, abs_error); |
| 2971 | + EXPECT_NEAR(expected_approx_selections_per_tied_host, host_4_counts, abs_error); |
| 2972 | +} |
| 2973 | + |
2883 | 2974 | TEST_P(LeastRequestLoadBalancerTest, WeightImbalance) { |
2884 | 2975 | hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", simTime(), 1), |
2885 | 2976 | makeTestHost(info_, "tcp://127.0.0.1:81", simTime(), 2)}; |
|
0 commit comments