|
|
|
@ -99,6 +99,7 @@ constexpr char kDefaultLocalityZone[] = "xds_default_locality_zone"; |
|
|
|
|
constexpr char kLbDropType[] = "lb"; |
|
|
|
|
constexpr char kThrottleDropType[] = "throttle"; |
|
|
|
|
constexpr int kDefaultLocalityWeight = 3; |
|
|
|
|
constexpr int kDefaultLocalityPriority = 0; |
|
|
|
|
|
|
|
|
|
template <typename ServiceType> |
|
|
|
|
class CountedService : public ServiceType { |
|
|
|
@ -262,7 +263,8 @@ class EdsServiceImpl : public EdsService { |
|
|
|
|
struct ResponseArgs { |
|
|
|
|
struct Locality { |
|
|
|
|
Locality(const grpc::string& sub_zone, std::vector<int> ports, |
|
|
|
|
int lb_weight = kDefaultLocalityWeight, int priority = 0) |
|
|
|
|
int lb_weight = kDefaultLocalityWeight, |
|
|
|
|
int priority = kDefaultLocalityPriority) |
|
|
|
|
: sub_zone(std::move(sub_zone)), |
|
|
|
|
ports(std::move(ports)), |
|
|
|
|
lb_weight(lb_weight), |
|
|
|
@ -566,7 +568,7 @@ class XdsEnd2endTest : public ::testing::Test { |
|
|
|
|
|
|
|
|
|
void ShutdownBackend(size_t index) { backends_[index]->Shutdown(); } |
|
|
|
|
|
|
|
|
|
void ResetStub(int fallback_timeout = 0, |
|
|
|
|
void ResetStub(int fallback_timeout = 0, int failover_timeout = 0, |
|
|
|
|
const grpc::string& expected_targets = "", |
|
|
|
|
grpc::string scheme = "") { |
|
|
|
|
ChannelArguments args; |
|
|
|
@ -574,6 +576,9 @@ class XdsEnd2endTest : public ::testing::Test { |
|
|
|
|
if (fallback_timeout > 0) { |
|
|
|
|
args.SetInt(GRPC_ARG_XDS_FALLBACK_TIMEOUT_MS, fallback_timeout); |
|
|
|
|
} |
|
|
|
|
if (failover_timeout > 0) { |
|
|
|
|
args.SetInt(GRPC_ARG_XDS_FAILOVER_TIMEOUT_MS, failover_timeout); |
|
|
|
|
} |
|
|
|
|
args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, |
|
|
|
|
response_generator_.get()); |
|
|
|
|
if (!expected_targets.empty()) { |
|
|
|
@ -922,7 +927,7 @@ class XdsResolverTest : public XdsEnd2endTest { |
|
|
|
|
// used.
|
|
|
|
|
TEST_F(XdsResolverTest, XdsResolverIsUsed) { |
|
|
|
|
// Use xds-experimental scheme in URI.
|
|
|
|
|
ResetStub(0, "", "xds-experimental"); |
|
|
|
|
ResetStub(0, 0, "", "xds-experimental"); |
|
|
|
|
// Send an RPC to trigger resolution.
|
|
|
|
|
auto unused_result = SendRpc(); |
|
|
|
|
// Xds resolver returns xds_experimental as the LB policy.
|
|
|
|
@ -1067,7 +1072,7 @@ using SecureNamingTest = BasicTest; |
|
|
|
|
// Tests that secure naming check passes if target name is expected.
|
|
|
|
|
TEST_F(SecureNamingTest, TargetNameIsExpected) { |
|
|
|
|
// TODO(juanlishen): Use separate fake creds for the balancer channel.
|
|
|
|
|
ResetStub(0, kApplicationTargetName_ + ";lb"); |
|
|
|
|
ResetStub(0, 0, kApplicationTargetName_ + ";lb"); |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannel({balancers_[0]->port()}); |
|
|
|
|
const size_t kNumRpcsPerAddress = 100; |
|
|
|
@ -1098,7 +1103,7 @@ TEST_F(SecureNamingTest, TargetNameIsUnexpected) { |
|
|
|
|
// the name from the balancer doesn't match expectations.
|
|
|
|
|
ASSERT_DEATH_IF_SUPPORTED( |
|
|
|
|
{ |
|
|
|
|
ResetStub(0, kApplicationTargetName_ + ";lb"); |
|
|
|
|
ResetStub(0, 0, kApplicationTargetName_ + ";lb"); |
|
|
|
|
SetNextResolution({}, |
|
|
|
|
"{\n" |
|
|
|
|
" \"loadBalancingConfig\":[\n" |
|
|
|
@ -1287,6 +1292,151 @@ TEST_F(LocalityMapTest, UpdateMap) { |
|
|
|
|
EXPECT_EQ(2U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class FailoverTest : public BasicTest { |
|
|
|
|
public: |
|
|
|
|
FailoverTest() { ResetStub(0, 100, "", ""); } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Localities with the highest priority are used when multiple priority exist.
|
|
|
|
|
TEST_F(FailoverTest, ChooseHighestPriority) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForBackend(3, false); |
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(0, backends_[i]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
// The EDS service got a single request, and sent a single response.
|
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->request_count()); |
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If the higher priority localities are not reachable, failover to the highest
|
|
|
|
|
// priority among the rest.
|
|
|
|
|
TEST_F(FailoverTest, Failover) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, |
|
|
|
|
}); |
|
|
|
|
ShutdownBackend(3); |
|
|
|
|
ShutdownBackend(0); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForBackend(1, false); |
|
|
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
|
|
if (i == 1) continue; |
|
|
|
|
EXPECT_EQ(0, backends_[i]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
// The EDS service got a single request, and sent a single response.
|
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->request_count()); |
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If a locality with higher priority than the current one becomes ready,
|
|
|
|
|
// switch to it.
|
|
|
|
|
TEST_F(FailoverTest, SwitchBackToHigherPriority) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
const size_t kNumRpcs = 100; |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, |
|
|
|
|
}); |
|
|
|
|
ShutdownBackend(3); |
|
|
|
|
ShutdownBackend(0); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
WaitForBackend(1, false); |
|
|
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
|
|
if (i == 1) continue; |
|
|
|
|
EXPECT_EQ(0, backends_[i]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
StartBackend(0); |
|
|
|
|
WaitForBackend(0); |
|
|
|
|
CheckRpcSendOk(kNumRpcs); |
|
|
|
|
EXPECT_EQ(kNumRpcs, backends_[0]->backend_service()->request_count()); |
|
|
|
|
// The EDS service got a single request, and sent a single response.
|
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->request_count()); |
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The first update only contains unavailable priorities. The second update
|
|
|
|
|
// contains available priorities.
|
|
|
|
|
TEST_F(FailoverTest, UpdateInitialUnavailable) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 3}, |
|
|
|
|
}); |
|
|
|
|
ShutdownBackend(0); |
|
|
|
|
ShutdownBackend(1); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 1000); |
|
|
|
|
gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), |
|
|
|
|
gpr_time_from_millis(500, GPR_TIMESPAN)); |
|
|
|
|
// Send 0.5 second worth of RPCs.
|
|
|
|
|
do { |
|
|
|
|
CheckRpcSendFailure(); |
|
|
|
|
} while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); |
|
|
|
|
WaitForBackend(2, false); |
|
|
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
|
|
if (i == 2) continue; |
|
|
|
|
EXPECT_EQ(0, backends_[i]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
// The EDS service got a single request, and sent a single response.
|
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->request_count()); |
|
|
|
|
EXPECT_EQ(2U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that after the localities' priorities are updated, we still choose the
|
|
|
|
|
// highest READY priority with the updated localities.
|
|
|
|
|
TEST_F(FailoverTest, UpdatePriority) { |
|
|
|
|
SetNextResolution({}, kDefaultServiceConfig_.c_str()); |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
const size_t kNumRpcs = 100; |
|
|
|
|
EdsServiceImpl::ResponseArgs args({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 0); |
|
|
|
|
args = EdsServiceImpl::ResponseArgs({ |
|
|
|
|
{"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 2}, |
|
|
|
|
{"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 0}, |
|
|
|
|
{"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 1}, |
|
|
|
|
{"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 3}, |
|
|
|
|
}); |
|
|
|
|
ScheduleResponseForBalancer(0, EdsServiceImpl::BuildResponse(args), 1000); |
|
|
|
|
WaitForBackend(3, false); |
|
|
|
|
for (size_t i = 0; i < 3; ++i) { |
|
|
|
|
EXPECT_EQ(0, backends_[i]->backend_service()->request_count()); |
|
|
|
|
} |
|
|
|
|
WaitForBackend(1); |
|
|
|
|
CheckRpcSendOk(kNumRpcs); |
|
|
|
|
EXPECT_EQ(kNumRpcs, backends_[1]->backend_service()->request_count()); |
|
|
|
|
// The EDS service got a single request, and sent a single response.
|
|
|
|
|
EXPECT_EQ(1U, balancers_[0]->eds_service()->request_count()); |
|
|
|
|
EXPECT_EQ(2U, balancers_[0]->eds_service()->response_count()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
using DropTest = BasicTest; |
|
|
|
|
|
|
|
|
|
// Tests that RPCs are dropped according to the drop config.
|
|
|
|
@ -1760,9 +1910,9 @@ TEST_F(FallbackTest, FallbackModeIsExitedAfterChildRready) { |
|
|
|
|
SetNextResolutionForLbChannelAllBalancers(); |
|
|
|
|
// The state (TRANSIENT_FAILURE) update from the child policy will be ignored
|
|
|
|
|
// because we are still in fallback mode.
|
|
|
|
|
gpr_timespec deadline = gpr_time_add( |
|
|
|
|
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(5000, GPR_TIMESPAN)); |
|
|
|
|
// Send 5 seconds worth of RPCs.
|
|
|
|
|
gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), |
|
|
|
|
gpr_time_from_millis(500, GPR_TIMESPAN)); |
|
|
|
|
// Send 0.5 second worth of RPCs.
|
|
|
|
|
do { |
|
|
|
|
CheckRpcSendOk(); |
|
|
|
|
} while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); |
|
|
|
|