|
|
|
@ -96,7 +96,6 @@ constexpr char kEdsTypeUrl[] = |
|
|
|
|
"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment"; |
|
|
|
|
constexpr char kDefaultLocalityRegion[] = "xds_default_locality_region"; |
|
|
|
|
constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone"; |
|
|
|
|
constexpr char kDefaultLocalitySubzone[] = "xds_default_locality_subzone"; |
|
|
|
|
constexpr char kLbDropType[] = "lb"; |
|
|
|
|
constexpr char kThrottleDropType[] = "throttle"; |
|
|
|
|
constexpr int kDefaultLocalityWeight = 3; |
|
|
|
@ -260,6 +259,31 @@ class ClientStats { |
|
|
|
|
|
|
|
|
|
class EdsServiceImpl : public EdsService { |
|
|
|
|
public: |
|
|
|
|
struct ResponseArgs { |
|
|
|
|
struct Locality { |
|
|
|
|
Locality(const grpc::string& sub_zone, std::vector<int> ports, |
|
|
|
|
int lb_weight = kDefaultLocalityWeight, int priority = 0) |
|
|
|
|
: sub_zone(std::move(sub_zone)), |
|
|
|
|
ports(std::move(ports)), |
|
|
|
|
lb_weight(lb_weight), |
|
|
|
|
priority(priority) {} |
|
|
|
|
|
|
|
|
|
const grpc::string sub_zone; |
|
|
|
|
std::vector<int> ports; |
|
|
|
|
int lb_weight; |
|
|
|
|
int priority; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ResponseArgs() = default; |
|
|
|
|
explicit ResponseArgs(std::vector<Locality> locality_list) |
|
|
|
|
: locality_list(std::move(locality_list)) {} |
|
|
|
|
|
|
|
|
|
std::vector<Locality> locality_list; |
|
|
|
|
std::map<grpc::string, uint32_t> drop_categories; |
|
|
|
|
FractionalPercent::DenominatorType drop_denominator = |
|
|
|
|
FractionalPercent::MILLION; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>; |
|
|
|
|
using ResponseDelayPair = std::pair<DiscoveryResponse, int>; |
|
|
|
|
|
|
|
|
@ -317,47 +341,35 @@ class EdsServiceImpl : public EdsService { |
|
|
|
|
gpr_log(GPR_INFO, "LB[%p]: shut down", this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO(juanlishen): Put the args into a struct.
|
|
|
|
|
static DiscoveryResponse BuildResponse( |
|
|
|
|
const std::vector<std::vector<int>>& backend_ports, |
|
|
|
|
const std::vector<int>& lb_weights = {}, |
|
|
|
|
size_t first_locality_name_index = 0, |
|
|
|
|
const std::map<grpc::string, uint32_t>& drop_categories = {}, |
|
|
|
|
const FractionalPercent::DenominatorType denominator = |
|
|
|
|
FractionalPercent::MILLION) { |
|
|
|
|
static DiscoveryResponse BuildResponse(const ResponseArgs& args) { |
|
|
|
|
ClusterLoadAssignment assignment; |
|
|
|
|
assignment.set_cluster_name("service name"); |
|
|
|
|
for (size_t i = 0; i < backend_ports.size(); ++i) { |
|
|
|
|
for (const auto& locality : args.locality_list) { |
|
|
|
|
auto* endpoints = assignment.add_endpoints(); |
|
|
|
|
const int lb_weight = |
|
|
|
|
lb_weights.empty() ? kDefaultLocalityWeight : lb_weights[i]; |
|
|
|
|
endpoints->mutable_load_balancing_weight()->set_value(lb_weight); |
|
|
|
|
endpoints->set_priority(0); |
|
|
|
|
endpoints->mutable_load_balancing_weight()->set_value(locality.lb_weight); |
|
|
|
|
endpoints->set_priority(locality.priority); |
|
|
|
|
endpoints->mutable_locality()->set_region(kDefaultLocalityRegion); |
|
|
|
|
endpoints->mutable_locality()->set_zone(kDefaultLocalityZone); |
|
|
|
|
std::ostringstream sub_zone; |
|
|
|
|
sub_zone << kDefaultLocalitySubzone << '_' |
|
|
|
|
<< first_locality_name_index + i; |
|
|
|
|
endpoints->mutable_locality()->set_sub_zone(sub_zone.str()); |
|
|
|
|
for (const int& backend_port : backend_ports[i]) { |
|
|
|
|
endpoints->mutable_locality()->set_sub_zone(locality.sub_zone); |
|
|
|
|
for (const int& port : locality.ports) { |
|
|
|
|
auto* lb_endpoints = endpoints->add_lb_endpoints(); |
|
|
|
|
auto* endpoint = lb_endpoints->mutable_endpoint(); |
|
|
|
|
auto* address = endpoint->mutable_address(); |
|
|
|
|
auto* socket_address = address->mutable_socket_address(); |
|
|
|
|
socket_address->set_address("127.0.0.1"); |
|
|
|
|
socket_address->set_port_value(backend_port); |
|
|
|
|
socket_address->set_port_value(port); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!drop_categories.empty()) { |
|
|
|
|
if (!args.drop_categories.empty()) { |
|
|
|
|
auto* policy = assignment.mutable_policy(); |
|
|
|
|
for (const auto& p : drop_categories) { |
|
|
|
|
for (const auto& p : args.drop_categories) { |
|
|
|
|
const grpc::string& name = p.first; |
|
|
|
|
const uint32_t parts_per_million = p.second; |
|
|
|
|
auto* drop_overload = policy->add_drop_overloads(); |
|
|
|
|
drop_overload->set_category(name); |
|
|
|
|
auto* drop_percentage = drop_overload->mutable_drop_percentage(); |
|
|
|
|
drop_percentage->set_numerator(parts_per_million); |
|
|
|
|
drop_percentage->set_denominator(denominator); |
|
|
|
|
drop_percentage->set_denominator(args.drop_denominator); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
DiscoveryResponse response; |
|
|
|
@ -729,24 +741,6 @@ class XdsEnd2endTest : public ::testing::Test { |
|
|
|
|
return backend_ports; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const std::vector<std::vector<int>> GetBackendPortsInGroups( |
|
|
|
|
size_t start_index = 0, size_t stop_index = 0, |
|
|
|
|
size_t num_group = 1) const { |
|
|
|
|
if (stop_index == 0) stop_index = backends_.size(); |
|
|
|
|
size_t group_size = (stop_index - start_index) / num_group; |
|
|
|
|
std::vector<std::vector<int>> backend_ports; |
|
|
|
|
for (size_t i = 0; i < num_group; ++i) { |
|
|
|
|
backend_ports.emplace_back(); |
|
|
|
|
size_t group_start = group_size * i + start_index; |
|
|
|
|
size_t group_stop = |
|
|
|
|
i == num_group - 1 ? stop_index : group_start + group_size; |
|
|
|
|
for (size_t j = group_start; j < group_stop; ++j) { |
|
|
|
|
backend_ports[i].push_back(backends_[j]->port()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return backend_ports; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ScheduleResponseForBalancer(size_t i, const DiscoveryResponse& response, |
|
|
|
|
int delay_ms) { |
|
|
|
|
balancers_[i]->eds_service()->add_response(response, delay_ms); |
|
|
|
@ -938,8 +932,10 @@ TEST_F(SingleBalancerTest, Vanilla) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
const size_t kNumRpcsPerAddress = 100; |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse(GetBackendPortsInGroups()), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Make sure that trying to connect works without a call.
|
|
|
|
|
channel_->GetState(true /* try_to_connect */); |
|
|
|
|
// We need to wait for all backends to come online.
|
|
|
|
@ -962,17 +958,18 @@ TEST_F(SingleBalancerTest, SameBackendListedMultipleTimes) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// Same backend listed twice.
|
|
|
|
|
std::vector<int> ports; |
|
|
|
|
ports.push_back(backends_[0]->port()); |
|
|
|
|
ports.push_back(backends_[0]->port()); |
|
|
|
|
std::vector<int> ports(2, backends_[0]->port()); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", ports}, |
|
|
|
|
}); |
|
|
|
|
const size_t kNumRpcsPerAddress = 10; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse({ports}), 0); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// We need to wait for the backend to come online.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
|
// Send kNumRpcsPerAddress RPCs per server.
|
|
|
|
|
CheckRpcSendOk(kNumRpcsPerAddress * ports.size()); |
|
|
|
|
// Backend should have gotten 20 requests.
|
|
|
|
|
EXPECT_EQ(kNumRpcsPerAddress * 2, |
|
|
|
|
EXPECT_EQ(kNumRpcsPerAddress * ports.size(), |
|
|
|
|
backends_[0]->backend_service()->request_count()); |
|
|
|
|
// And they should have come from a single client port, because of
|
|
|
|
|
// subchannel sharing.
|
|
|
|
@ -985,8 +982,10 @@ TEST_F(SingleBalancerTest, SecureNaming) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannel({balancers_[0]->port()}); |
|
|
|
|
const size_t kNumRpcsPerAddress = 100; |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse(GetBackendPortsInGroups()), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Make sure that trying to connect works without a call.
|
|
|
|
|
channel_->GetState(true /* try_to_connect */); |
|
|
|
|
// We need to wait for all backends to come online.
|
|
|
|
@ -1031,11 +1030,17 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { |
|
|
|
|
const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); |
|
|
|
|
const int kCallDeadlineMs = kServerlistDelayMs * 2; |
|
|
|
|
// First response is an empty serverlist, sent right away.
|
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse({{}}), 0); |
|
|
|
|
// Send non-empty serverlist only after kServerlistDelayMs
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse(GetBackendPortsInGroups()), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
EdsServiceImpl::ResponseArgs::Locality empty_locality("locality0", {}); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
empty_locality, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Send non-empty serverlist only after kServerlistDelayMs.
|
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
const auto t0 = system_clock::now(); |
|
|
|
|
// Client will block: LB will initially send empty serverlist.
|
|
|
|
|
CheckRpcSendOk(1, kCallDeadlineMs, true /* wait_for_ready */); |
|
|
|
@ -1061,7 +1066,10 @@ TEST_F(SingleBalancerTest, AllServersUnreachableFailFast) { |
|
|
|
|
for (size_t i = 0; i < kNumUnreachableServers; ++i) { |
|
|
|
|
ports.push_back(grpc_pick_unused_port_or_die()); |
|
|
|
|
} |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse({ports}), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", ports}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
const Status status = SendRpc(); |
|
|
|
|
// The error shouldn't be DEADLINE_EXCEEDED.
|
|
|
|
|
EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code()); |
|
|
|
@ -1082,11 +1090,11 @@ TEST_F(SingleBalancerTest, LocalityMapWeightedRoundRobin) { |
|
|
|
|
const double kLocalityWeightRate1 = |
|
|
|
|
static_cast<double>(kLocalityWeight1) / kTotalLocalityWeight; |
|
|
|
|
// EDS response contains 2 localities, each of which contains 1 backend.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups(0, 2, 2), |
|
|
|
|
{kLocalityWeight0, kLocalityWeight1}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kLocalityWeight0}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kLocalityWeight1}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Wait for both backends to be ready.
|
|
|
|
|
WaitForAllBackends(1, 0, 2); |
|
|
|
|
// Send kNumRpcs RPCs.
|
|
|
|
@ -1118,14 +1126,19 @@ TEST_F(SingleBalancerTest, LocalityMapStressTest) { |
|
|
|
|
const size_t kNumLocalities = 100; |
|
|
|
|
// The first EDS response contains kNumLocalities localities, each of which
|
|
|
|
|
// contains backend 0.
|
|
|
|
|
const std::vector<std::vector<int>> locality_list_0(kNumLocalities, |
|
|
|
|
{backends_[0]->port()}); |
|
|
|
|
EdsServiceImpl::ResponseArgs args; |
|
|
|
|
for (size_t i = 0; i < kNumLocalities; ++i) { |
|
|
|
|
grpc::string name = "locality" + std::to_string(i); |
|
|
|
|
EdsServiceImpl::ResponseArgs::Locality locality(name, |
|
|
|
|
{backends_[0]->port()}); |
|
|
|
|
args.locality_list.emplace_back(std::move(locality)); |
|
|
|
|
} |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// The second EDS response contains 1 locality, which contains backend 1.
|
|
|
|
|
const std::vector<std::vector<int>> locality_list_1 = |
|
|
|
|
GetBackendPortsInGroups(1, 2); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(locality_list_0), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(locality_list_1), |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", GetBackendPorts(1, 2)}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), |
|
|
|
|
60 * 1000); |
|
|
|
|
// Wait until backend 0 is ready, before which kNumLocalities localities are
|
|
|
|
|
// received and handled by the xds policy.
|
|
|
|
@ -1162,20 +1175,18 @@ TEST_F(SingleBalancerTest, LocalityMapUpdate) { |
|
|
|
|
for (int weight : kLocalityWeights1) { |
|
|
|
|
locality_weight_rate_1.push_back(weight / kTotalLocalityWeight1); |
|
|
|
|
} |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(0 /*start_index*/, 3 /*stop_index*/, |
|
|
|
|
3 /*num_group*/), |
|
|
|
|
kLocalityWeights0), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(1 /*start_index*/, 4 /*stop_index*/, |
|
|
|
|
3 /*num_group*/), |
|
|
|
|
kLocalityWeights1, 1 /*first_locality_name_index*/), |
|
|
|
|
5000); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), 2}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), 3}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), 4}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), 3}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), 2}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), 6}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 5000); |
|
|
|
|
// Wait for the first 3 backends to be ready.
|
|
|
|
|
WaitForAllBackends(1, 0, 3); |
|
|
|
|
gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); |
|
|
|
@ -1244,13 +1255,12 @@ TEST_F(SingleBalancerTest, Drop) { |
|
|
|
|
const double KDropRateForLbAndThrottle = |
|
|
|
|
kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; |
|
|
|
|
// The EDS response contains two drop categories.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForAllBackends(); |
|
|
|
|
// Send kNumRpcs RPCs and count the drops.
|
|
|
|
|
size_t num_drops = 0; |
|
|
|
@ -1286,12 +1296,12 @@ TEST_F(SingleBalancerTest, DropPerHundred) { |
|
|
|
|
const uint32_t kDropPerHundredForLb = 10; |
|
|
|
|
const double kDropRateForLb = kDropPerHundredForLb / 100.0; |
|
|
|
|
// The EDS response contains one drop category.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerHundredForLb}}, |
|
|
|
|
FractionalPercent::HUNDRED), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerHundredForLb}}; |
|
|
|
|
args.drop_denominator = FractionalPercent::HUNDRED; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForAllBackends(); |
|
|
|
|
// Send kNumRpcs RPCs and count the drops.
|
|
|
|
|
size_t num_drops = 0; |
|
|
|
@ -1326,12 +1336,12 @@ TEST_F(SingleBalancerTest, DropPerTenThousand) { |
|
|
|
|
const uint32_t kDropPerTenThousandForLb = 1000; |
|
|
|
|
const double kDropRateForLb = kDropPerTenThousandForLb / 10000.0; |
|
|
|
|
// The EDS response contains one drop category.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerTenThousandForLb}}, |
|
|
|
|
FractionalPercent::TEN_THOUSAND), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerTenThousandForLb}}; |
|
|
|
|
args.drop_denominator = FractionalPercent::TEN_THOUSAND; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForAllBackends(); |
|
|
|
|
// Send kNumRpcs RPCs and count the drops.
|
|
|
|
|
size_t num_drops = 0; |
|
|
|
@ -1370,22 +1380,18 @@ TEST_F(SingleBalancerTest, DropUpdate) { |
|
|
|
|
const double KDropRateForLbAndThrottle = |
|
|
|
|
kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; |
|
|
|
|
// The first EDS response contains one drop category.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerMillionForLb}}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerMillionForLb}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// The second EDS response contains two drop categories.
|
|
|
|
|
// TODO(juanlishen): Change the EDS response sending to deterministic style
|
|
|
|
|
// (e.g., by using condition variable) so that we can shorten the test
|
|
|
|
|
// duration.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}), |
|
|
|
|
10000); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 10000); |
|
|
|
|
WaitForAllBackends(); |
|
|
|
|
// Send kNumRpcs RPCs and count the drops.
|
|
|
|
|
size_t num_drops = 0; |
|
|
|
@ -1465,13 +1471,12 @@ TEST_F(SingleBalancerTest, DropAll) { |
|
|
|
|
const uint32_t kDropPerMillionForLb = 100000; |
|
|
|
|
const uint32_t kDropPerMillionForThrottle = 1000000; |
|
|
|
|
// The EDS response contains two drop categories.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Send kNumRpcs RPCs and all of them are dropped.
|
|
|
|
|
for (size_t i = 0; i < kNumRpcs; ++i) { |
|
|
|
|
EchoResponse response; |
|
|
|
@ -1493,11 +1498,11 @@ TEST_F(SingleBalancerTest, Fallback) { |
|
|
|
|
kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// Send non-empty serverlist only after kServerlistDelayMs.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(kNumBackendsInResolution /* start_index */)), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(kNumBackendsInResolution)}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
// Wait until all the fallback backends are reachable.
|
|
|
|
|
WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, |
|
|
|
|
kNumBackendsInResolution /* stop_index */); |
|
|
|
@ -1542,12 +1547,12 @@ TEST_F(SingleBalancerTest, FallbackUpdate) { |
|
|
|
|
kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// Send non-empty serverlist only after kServerlistDelayMs.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups( |
|
|
|
|
kNumBackendsInResolution + |
|
|
|
|
kNumBackendsInResolutionUpdate /* start_index */)), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(kNumBackendsInResolution + |
|
|
|
|
kNumBackendsInResolutionUpdate)}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), |
|
|
|
|
kServerlistDelayMs); |
|
|
|
|
// Wait until all the fallback backends are reachable.
|
|
|
|
|
WaitForAllBackends(1 /* num_requests_multiple_of */, 0 /* start_index */, |
|
|
|
|
kNumBackendsInResolution /* stop_index */); |
|
|
|
@ -1645,8 +1650,10 @@ TEST_F(SingleBalancerTest, FallbackIfResponseReceivedButChildNotReady) { |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// Send a serverlist that only contains an unreachable backend before fallback
|
|
|
|
|
// timeout.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse({{grpc_pick_unused_port_or_die()}}), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {grpc_pick_unused_port_or_die()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Because no child policy is ready before fallback timeout, we enter fallback
|
|
|
|
|
// mode.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
@ -1659,11 +1666,11 @@ TEST_F(SingleBalancerTest, FallbackModeIsExitedWhenBalancerSaysToDropAllCalls) { |
|
|
|
|
// Enter fallback mode because the LB channel fails to connect.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
|
// Return a new balancer that sends a response to drop all calls.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse(GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, 1000000}}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, 1000000}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// Send RPCs until failure.
|
|
|
|
|
gpr_timespec deadline = gpr_time_add( |
|
|
|
@ -1683,8 +1690,10 @@ TEST_F(SingleBalancerTest, FallbackModeIsExitedAfterChildRready) { |
|
|
|
|
WaitForBackend(0); |
|
|
|
|
// Return a new balancer that sends a dead backend.
|
|
|
|
|
ShutdownBackend(1); |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse({{backends_[1]->port()}}), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {backends_[1]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// The state (TRANSIENT_FAILURE) update from the child policy will be ignored
|
|
|
|
|
// because we are still in fallback mode.
|
|
|
|
@ -1708,8 +1717,10 @@ TEST_F(SingleBalancerTest, FallbackModeIsExitedAfterChildRready) { |
|
|
|
|
TEST_F(SingleBalancerTest, BackendsRestart) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, EdsServiceImpl::BuildResponse(GetBackendPortsInGroups()), 0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForAllBackends(); |
|
|
|
|
// Stop backends. RPCs should fail.
|
|
|
|
|
ShutdownAllBackends(); |
|
|
|
@ -1728,12 +1739,14 @@ class UpdatesTest : public XdsEnd2endTest { |
|
|
|
|
TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
auto first_backend = GetBackendPortsInGroups(0, 1); |
|
|
|
|
auto second_backend = GetBackendPortsInGroups(1, 2); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(first_backend), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(second_backend), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {backends_[0]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", {backends_[1]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
|
|
|
|
|
// Wait until the first backend is ready.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
@ -1781,12 +1794,14 @@ TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { |
|
|
|
|
TEST_F(UpdatesTest, UpdateBalancerName) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
auto first_backend = GetBackendPortsInGroups(0, 1); |
|
|
|
|
auto second_backend = GetBackendPortsInGroups(1, 2); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(first_backend), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(second_backend), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {backends_[0]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", {backends_[1]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
|
|
|
|
|
// Wait until the first backend is ready.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
@ -1852,12 +1867,14 @@ TEST_F(UpdatesTest, UpdateBalancerName) { |
|
|
|
|
TEST_F(UpdatesTest, UpdateBalancersRepeated) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
auto first_backend = GetBackendPortsInGroups(0, 1); |
|
|
|
|
auto second_backend = GetBackendPortsInGroups(1, 2); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(first_backend), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(second_backend), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {backends_[0]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", {backends_[1]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
|
|
|
|
|
// Wait until the first backend is ready.
|
|
|
|
|
WaitForBackend(0); |
|
|
|
@ -1920,12 +1937,14 @@ TEST_F(UpdatesTest, UpdateBalancersRepeated) { |
|
|
|
|
TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannel({balancers_[0]->port()}); |
|
|
|
|
auto first_backend = GetBackendPortsInGroups(0, 1); |
|
|
|
|
auto second_backend = GetBackendPortsInGroups(1, 2); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(first_backend), |
|
|
|
|
0); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(second_backend), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", {backends_[0]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", {backends_[1]->port()}}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(1, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
|
|
|
|
|
// Start servers and send 10 RPCs per server.
|
|
|
|
|
gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); |
|
|
|
@ -2007,10 +2026,10 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) { |
|
|
|
|
const size_t kNumRpcsPerAddress = 100; |
|
|
|
|
// TODO(juanlishen): Partition the backends after multiple localities is
|
|
|
|
|
// tested.
|
|
|
|
|
ScheduleResponseForBalancer(0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(0, backends_.size())), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Wait until all backends are ready.
|
|
|
|
|
int num_ok = 0; |
|
|
|
|
int num_failure = 0; |
|
|
|
@ -2046,11 +2065,10 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, BalancerRestart) { |
|
|
|
|
const size_t kNumBackendsFirstPass = backends_.size() / 2; |
|
|
|
|
const size_t kNumBackendsSecondPass = |
|
|
|
|
backends_.size() - kNumBackendsFirstPass; |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(0, kNumBackendsFirstPass)), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, kNumBackendsFirstPass)}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Wait until all backends returned by the balancer are ready.
|
|
|
|
|
int num_ok = 0; |
|
|
|
|
int num_failure = 0; |
|
|
|
@ -2077,11 +2095,10 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, BalancerRestart) { |
|
|
|
|
} |
|
|
|
|
// Now restart the balancer, this time pointing to the new backends.
|
|
|
|
|
balancers_[0]->Start(server_host_); |
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(kNumBackendsFirstPass)), |
|
|
|
|
0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", GetBackendPorts(kNumBackendsFirstPass)}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
// Wait for queries to start going to one of the new backends.
|
|
|
|
|
// This tells us that we're now using the new serverlist.
|
|
|
|
|
std::tie(num_ok, num_failure, num_drops) = |
|
|
|
@ -2116,13 +2133,12 @@ TEST_F(SingleBalancerWithClientLoadReportingAndDropTest, Vanilla) { |
|
|
|
|
const double KDropRateForLbAndThrottle = |
|
|
|
|
kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; |
|
|
|
|
// The EDS response contains two drop categories.
|
|
|
|
|
ScheduleResponseForBalancer( |
|
|
|
|
0, |
|
|
|
|
EdsServiceImpl::BuildResponse( |
|
|
|
|
GetBackendPortsInGroups(), {}, 0, |
|
|
|
|
{{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}), |
|
|
|
|
0); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts()}, |
|
|
|
|
}); |
|
|
|
|
args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, |
|
|
|
|
{kThrottleDropType, kDropPerMillionForThrottle}}; |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
int num_ok = 0; |
|
|
|
|
int num_failure = 0; |
|
|
|
|
int num_drops = 0; |
|
|
|
|