YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/integration-tests/load_balancer-test.cc
Line
Count
Source
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include <gtest/gtest.h>
15
16
#include "yb/client/client.h"
17
18
#include "yb/consensus/consensus.pb.h"
19
#include "yb/consensus/consensus.proxy.h"
20
21
#include "yb/gutil/casts.h"
22
23
#include "yb/integration-tests/external_mini_cluster.h"
24
#include "yb/integration-tests/yb_table_test_base.h"
25
26
#include "yb/master/master_cluster.proxy.h"
27
28
#include "yb/tools/yb-admin_client.h"
29
30
#include "yb/util/monotime.h"
31
#include "yb/util/result.h"
32
33
using namespace std::literals;
34
35
namespace yb {
36
namespace integration_tests {
37
38
const auto kDefaultTimeout = 30000ms;
39
40
class LoadBalancerTest : public YBTableTestBase {
41
 protected:
42
8
  bool use_yb_admin_client() override { return true; }
43
44
143
  bool use_external_mini_cluster() override { return true; }
45
46
6
  int num_tablets() override {
47
6
    return 4;
48
6
  }
49
50
4
  bool enable_ysql() override {
51
    // Do not create the transaction status table.
52
4
    return false;
53
4
  }
54
55
115
  Result<bool> AreLeadersOnPreferredOnly() {
56
115
    master::AreLeadersOnPreferredOnlyRequestPB req;
57
115
    master::AreLeadersOnPreferredOnlyResponsePB resp;
58
115
    rpc::RpcController rpc;
59
115
    rpc.set_timeout(kDefaultTimeout);
60
115
    auto proxy = GetMasterLeaderProxy<master::MasterClusterProxy>();
61
115
    RETURN_NOT_OK(proxy.AreLeadersOnPreferredOnly(req, &resp, &rpc));
62
115
    return !resp.has_error();
63
115
  }
64
65
3
  void CustomizeExternalMiniCluster(ExternalMiniClusterOptions* opts) override {
66
3
    opts->extra_tserver_flags.push_back("--placement_cloud=c");
67
3
    opts->extra_tserver_flags.push_back("--placement_region=r");
68
3
    opts->extra_tserver_flags.push_back("--placement_zone=z${index}");
69
3
  }
70
71
};
72
73
1
TEST_F(LoadBalancerTest, PreferredZoneAddNode) {
74
1
  ASSERT_OK(yb_admin_client_->ModifyPlacementInfo("c.r.z0,c.r.z1,c.r.z2", 3, ""));
75
1
  ASSERT_OK(yb_admin_client_->SetPreferredZones({"c.r.z1"}));
76
77
1
  ASSERT_OK(WaitFor([&]() {
78
1
    return AreLeadersOnPreferredOnly();
79
1
  }, kDefaultTimeout, "AreLeadersOnPreferredOnly"));
80
81
1
  std::vector<std::string> extra_opts;
82
1
  extra_opts.push_back("--placement_cloud=c");
83
1
  extra_opts.push_back("--placement_region=r");
84
1
  extra_opts.push_back("--placement_zone=z1");
85
1
  ASSERT_OK(external_mini_cluster()->AddTabletServer(true, extra_opts));
86
87
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
88
1
    return client_->IsLoadBalanced(narrow_cast<uint32_t>(num_tablet_servers() + 1));
89
1
  },  kDefaultTimeout * 2, "IsLoadBalanced"));
90
91
1
  auto firstLoad = ASSERT_RESULT(GetLoadOnTserver(external_mini_cluster()->tablet_server(1)));
92
1
  auto secondLoad = ASSERT_RESULT(GetLoadOnTserver(external_mini_cluster()->tablet_server(3)));
93
  // Now assert that both tablet servers in zone z1 have the same count.
94
1
  ASSERT_EQ(firstLoad, secondLoad);
95
1
}
96
97
// Test load balancer idle / active:
98
// 1. Add tserver.
99
// 2. Check that load balancer becomes active and completes balancing load.
100
// 3. Delete table should not activate the load balancer. Not triggered through LB.
101
1
TEST_F(LoadBalancerTest, IsLoadBalancerIdle) {
102
1
  ASSERT_OK(yb_admin_client_->ModifyPlacementInfo("c.r.z0,c.r.z1,c.r.z2", 3, ""));
103
104
1
  std::vector<std::string> extra_opts;
105
1
  extra_opts.push_back("--placement_cloud=c");
106
1
  extra_opts.push_back("--placement_region=r");
107
1
  extra_opts.push_back("--placement_zone=z1");
108
1
  ASSERT_OK(external_mini_cluster()->AddTabletServer(true, extra_opts));
109
1
  ASSERT_OK(external_mini_cluster()->WaitForTabletServerCount(num_tablet_servers() + 1,
110
1
      kDefaultTimeout));
111
112
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
113
1
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
114
1
    return !is_idle;
115
1
  },  kDefaultTimeout * 2, "IsLoadBalancerActive"));
116
117
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
118
1
    return client_->IsLoadBalancerIdle();
119
1
  },  kDefaultTimeout * 2, "IsLoadBalancerIdle"));
120
121
1
  YBTableTestBase::DeleteTable();
122
  // Assert that this times out.
123
1
  ASSERT_NOK(WaitFor([&]() -> Result<bool> {
124
1
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
125
1
    return !is_idle;
126
1
  },  MonoDelta::FromMilliseconds(10000), "IsLoadBalancerActive"));
127
1
}
128
129
// This regression test is to check that we don't hit the CHECK in cluster_balance.cc
130
//  state_->pending_stepdown_leader_tasks_[tablet->table()->id()].count(tablet->tablet_id()) == 0
131
// This CHECK was previously hit when load_balancer_max_concurrent_moves was set to a value > 1
132
// and multiple stepdown tasks were sent to the same tablet on subsequent LB runs.
133
1
TEST_F(LoadBalancerTest, PendingLeaderStepdownRegressTest) {
134
1
  const int test_bg_task_wait_ms = 1000;
135
1
  ASSERT_OK(yb_admin_client_->ModifyPlacementInfo("c.r.z0,c.r.z1,c.r.z2", 3, ""));
136
1
  ASSERT_OK(yb_admin_client_->SetPreferredZones({"c.r.z1"}));
137
138
  // Move all leaders to one tablet.
139
1
  ASSERT_OK(WaitFor([&]() {
140
1
    return AreLeadersOnPreferredOnly();
141
1
  }, kDefaultTimeout, "AreLeadersOnPreferredOnly"));
142
143
  // Allow for multiple leader moves per table.
144
2
  for (size_t i = 0; i < num_masters(); ++i) {
145
1
    ASSERT_OK(external_mini_cluster_->SetFlag(external_mini_cluster_->master(i),
146
1
                                              "load_balancer_max_concurrent_moves", "10"));
147
1
    ASSERT_OK(external_mini_cluster_->SetFlag(external_mini_cluster_->master(i),
148
1
                                              "load_balancer_max_concurrent_moves_per_table", "5"));
149
1
    ASSERT_OK(external_mini_cluster_->SetFlag(external_mini_cluster_->master(i),
150
1
                                              "catalog_manager_bg_task_wait_ms",
151
1
                                              std::to_string(test_bg_task_wait_ms)));
152
1
  }
153
  // Add stepdown delay of 2 * catalog_manager_bg_task_wait_ms.
154
  // This ensures that we will have pending stepdown tasks during a subsequent LB run.
155
4
  for (size_t i = 0; i < num_tablet_servers(); ++i) {
156
3
    ASSERT_OK(external_mini_cluster_->SetFlag(external_mini_cluster_->tablet_server(i),
157
3
                                              "TEST_leader_stepdown_delay_ms",
158
3
                                              std::to_string(2 * test_bg_task_wait_ms)));
159
3
  }
160
161
  // Trigger leader balancing.
162
1
  ASSERT_OK(yb_admin_client_->SetPreferredZones({"c.r.z0", "c.r.z1", "c.r.z2"}));
163
164
  // Wait for load balancing to complete.
165
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
166
1
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
167
1
    return !is_idle;
168
1
  },  kDefaultTimeout * 2, "IsLoadBalancerActive"));
169
170
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
171
1
    return client_->IsLoadBalancerIdle();
172
1
  },  kDefaultTimeout * 2, "IsLoadBalancerIdle"));
173
1
}
174
175
class LoadBalancerOddTabletsTest : public LoadBalancerTest {
176
 protected:
177
2
  int num_tablets() override {
178
2
    return 3;
179
2
  }
180
181
1
  void CustomizeExternalMiniCluster(ExternalMiniClusterOptions* opts) override {
182
1
    opts->extra_tserver_flags.push_back("--placement_cloud=c");
183
1
    opts->extra_tserver_flags.push_back("--placement_region=r");
184
1
    opts->extra_tserver_flags.push_back("--placement_zone=z${index}");
185
1
    opts->extra_master_flags.push_back("--load_balancer_max_over_replicated_tablets=5");
186
1
  }
187
};
188
189
1
TEST_F_EX(LoadBalancerTest, MultiZoneTest, LoadBalancerOddTabletsTest) {
190
1
  ASSERT_OK(yb_admin_client_->ModifyPlacementInfo("c.r.z0,c.r.z1,c.r.z2", 3, ""));
191
192
1
  std::vector<std::string> extra_opts;
193
1
  extra_opts.push_back("--placement_cloud=c");
194
1
  extra_opts.push_back("--placement_region=r");
195
1
  extra_opts.push_back("--placement_zone=z1");
196
1
  ASSERT_OK(external_mini_cluster()->AddTabletServer(true, extra_opts));
197
198
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
199
1
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
200
1
    return !is_idle;
201
1
  },  kDefaultTimeout * 2, "IsLoadBalancerActive"));
202
203
1
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
204
1
    return client_->IsLoadBalanced(narrow_cast<int>(num_tablet_servers() + 1));
205
1
  },  kDefaultTimeout * 2, "IsLoadBalanced"));
206
1
}
207
208
} // namespace integration_tests
209
} // namespace yb