|
|
|
@ -971,9 +971,12 @@ TEST_P(RingHashTest, ReattemptWhenAllEndpointsUnreachable) { |
|
|
|
|
{"address_hash", CreateMetadataValueThatHashesToBackend(0)}}; |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false)); |
|
|
|
|
ShutdownBackend(0); |
|
|
|
|
CheckRpcSendFailure(DEBUG_LOCATION, |
|
|
|
|
CheckRpcSendFailureOptions().set_rpc_options( |
|
|
|
|
RpcOptions().set_metadata(std::move(metadata)))); |
|
|
|
|
CheckRpcSendFailure( |
|
|
|
|
DEBUG_LOCATION, StatusCode::UNAVAILABLE, |
|
|
|
|
"ring hash cannot find a connected subchannel; first failure: " |
|
|
|
|
"(UNKNOWN: Failed to connect to remote host: Connection refused|" |
|
|
|
|
"UNAVAILABLE: Failed to connect to remote host: FD shutdown)", |
|
|
|
|
RpcOptions().set_metadata(std::move(metadata))); |
|
|
|
|
StartBackend(0); |
|
|
|
|
// Ensure we are actively connecting without any traffic.
|
|
|
|
|
EXPECT_TRUE(channel_->WaitForConnected( |
|
|
|
@ -1003,20 +1006,31 @@ TEST_P(RingHashTest, TransientFailureSkipToAvailableReady) { |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
std::vector<std::pair<std::string, std::string>> metadata = { |
|
|
|
|
{"address_hash", CreateMetadataValueThatHashesToBackend(0)}}; |
|
|
|
|
const auto rpc_options = RpcOptions().set_metadata(std::move(metadata)); |
|
|
|
|
const auto rpc_options = RpcOptions() |
|
|
|
|
.set_metadata(std::move(metadata)) |
|
|
|
|
.set_timeout_ms(kConnectionTimeoutMilliseconds); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false)); |
|
|
|
|
gpr_log(GPR_INFO, "=== SENDING FIRST RPC ==="); |
|
|
|
|
CheckRpcSendFailure( |
|
|
|
|
DEBUG_LOCATION, |
|
|
|
|
CheckRpcSendFailureOptions().set_rpc_options(rpc_options)); |
|
|
|
|
DEBUG_LOCATION, StatusCode::UNAVAILABLE, |
|
|
|
|
"ring hash cannot find a connected subchannel; first failure: " |
|
|
|
|
"(UNKNOWN: Failed to connect to remote host: Connection refused|" |
|
|
|
|
"UNAVAILABLE: Failed to connect to remote host: FD shutdown)", |
|
|
|
|
rpc_options); |
|
|
|
|
gpr_log(GPR_INFO, "=== DONE WITH FIRST RPC ==="); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel_->GetState(false)); |
|
|
|
|
// Bring up backend 0. The channel should become connected without
|
|
|
|
|
// any picks, because in TF, we are always trying to connect to at
|
|
|
|
|
// least one backend at all times.
|
|
|
|
|
gpr_log(GPR_INFO, "=== STARTING BACKEND 0 ==="); |
|
|
|
|
StartBackend(0); |
|
|
|
|
gpr_log(GPR_INFO, "=== WAITING FOR CHANNEL TO BECOME READY ==="); |
|
|
|
|
EXPECT_TRUE(channel_->WaitForConnected( |
|
|
|
|
grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds))); |
|
|
|
|
// RPCs should go to backend 0.
|
|
|
|
|
gpr_log(GPR_INFO, "=== WAITING FOR BACKEND 0 ==="); |
|
|
|
|
WaitForBackend(DEBUG_LOCATION, 0, WaitForBackendOptions(), rpc_options); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_READY, channel_->GetState(false)); |
|
|
|
|
// Bring down backend 0 and bring up backend 1.
|
|
|
|
|
// Note the RPC contains a header value that will always be hashed to
|
|
|
|
|
// backend 0. So by purposely bringing down backend 0 and bringing up another
|
|
|
|
@ -1025,14 +1039,66 @@ TEST_P(RingHashTest, TransientFailureSkipToAvailableReady) { |
|
|
|
|
// Since the the entries in the ring are pretty distributed and we have
|
|
|
|
|
// unused ports to fill the ring, it is almost guaranteed that the Picker
|
|
|
|
|
// will go through some non-READY entries and skip them as per design.
|
|
|
|
|
gpr_log(GPR_INFO, "=== SHUTTING DOWN BACKEND 0 ==="); |
|
|
|
|
ShutdownBackend(0); |
|
|
|
|
gpr_log(GPR_INFO, "=== WAITING FOR STATE CHANGE ==="); |
|
|
|
|
EXPECT_TRUE(channel_->WaitForStateChange( |
|
|
|
|
GRPC_CHANNEL_READY, |
|
|
|
|
grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds))); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel_->GetState(false)); |
|
|
|
|
gpr_log(GPR_INFO, "=== SENDING SECOND RPC ==="); |
|
|
|
|
CheckRpcSendFailure( |
|
|
|
|
DEBUG_LOCATION, |
|
|
|
|
CheckRpcSendFailureOptions().set_rpc_options(rpc_options)); |
|
|
|
|
DEBUG_LOCATION, StatusCode::UNAVAILABLE, |
|
|
|
|
"ring hash cannot find a connected subchannel; first failure: " |
|
|
|
|
"(UNKNOWN: Failed to connect to remote host: Connection refused|" |
|
|
|
|
"UNAVAILABLE: Failed to connect to remote host: FD shutdown)", |
|
|
|
|
rpc_options); |
|
|
|
|
gpr_log(GPR_INFO, "=== STARTING BACKEND 1 ==="); |
|
|
|
|
StartBackend(1); |
|
|
|
|
gpr_log(GPR_INFO, "=== WAITING FOR CHANNEL TO BECOME READY ==="); |
|
|
|
|
EXPECT_TRUE(channel_->WaitForConnected( |
|
|
|
|
grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds))); |
|
|
|
|
gpr_log(GPR_INFO, "=== WAITING FOR BACKEND 1 ==="); |
|
|
|
|
WaitForBackend(DEBUG_LOCATION, 1, WaitForBackendOptions(), rpc_options); |
|
|
|
|
gpr_log(GPR_INFO, "=== DONE ==="); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This tests a bug seen in the wild where ring_hash started with no
|
|
|
|
|
// endpoints and reported TRANSIENT_FAILURE, then got an update with
|
|
|
|
|
// endpoints and reported IDLE, but the picker update was squelched, so
|
|
|
|
|
// it failed to ever get reconnected.
|
|
|
|
|
TEST_P(RingHashTest, ReattemptWhenGoingFromTransientFailureToIdle) { |
|
|
|
|
CreateAndStartBackends(1); |
|
|
|
|
const uint32_t kConnectionTimeoutMilliseconds = 5000; |
|
|
|
|
auto cluster = default_cluster_; |
|
|
|
|
cluster.set_lb_policy(Cluster::RING_HASH); |
|
|
|
|
balancer_->ads_service()->SetCdsResource(cluster); |
|
|
|
|
auto new_route_config = default_route_config_; |
|
|
|
|
SetListenerAndRouteConfiguration(balancer_.get(), default_listener_, |
|
|
|
|
new_route_config); |
|
|
|
|
// Send empty EDS update.
|
|
|
|
|
EdsResourceArgs args( |
|
|
|
|
{{"locality0", std::vector<EdsResourceArgs::Endpoint>()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false)); |
|
|
|
|
// Channel should fail RPCs and go into TRANSIENT_FAILURE.
|
|
|
|
|
CheckRpcSendFailure( |
|
|
|
|
DEBUG_LOCATION, StatusCode::UNAVAILABLE, |
|
|
|
|
// TODO(roth): As part of https://github.com/grpc/grpc/issues/22883,
|
|
|
|
|
// figure out how to get a useful resolution note plumbed down to
|
|
|
|
|
// improve this message.
|
|
|
|
|
"empty address list: ", |
|
|
|
|
RpcOptions().set_timeout_ms(kConnectionTimeoutMilliseconds)); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_TRANSIENT_FAILURE, channel_->GetState(false)); |
|
|
|
|
// Send EDS update with 1 backend.
|
|
|
|
|
args = EdsResourceArgs({{"locality0", CreateEndpointsForBackends()}}); |
|
|
|
|
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args)); |
|
|
|
|
// A wait_for_ready RPC should succeed, and the channel should report READY.
|
|
|
|
|
CheckRpcSendOk(DEBUG_LOCATION, 1, |
|
|
|
|
RpcOptions() |
|
|
|
|
.set_timeout_ms(kConnectionTimeoutMilliseconds) |
|
|
|
|
.set_wait_for_ready(true)); |
|
|
|
|
EXPECT_EQ(GRPC_CHANNEL_READY, channel_->GetState(false)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test unspported hash policy types are all ignored before a supported
|
|
|
|
|