xds: populate envoy RetryPolicy with no retryOn to resolver (#8511)

Envoy RetryPolicy with empty retryOn should not be ignored as no retry config when selecting Route config. Therefore, if xDS update for a route contains a RetryPolicy that has no RetryOn value that we support, but the virtual host config does, xds client should choose the Envoy RetryPolicy from the route (even with no RetryOn), rather than choosing the one from virtual host, and try to convert it into grpc RetryPolicy, and end up with no retry.
This commit is contained in:
ZHANG Dapeng 2021-09-13 08:31:00 -07:00 committed by GitHub
parent 7a65c74283
commit 9ff54059d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 11 deletions

View File

@ -1273,13 +1273,10 @@ final class ClientXdsClient extends AbstractXdsClient {
retryableStatusCodesBuilder.add(code);
}
List<Code> retryableStatusCodes = retryableStatusCodesBuilder.build();
if (!retryableStatusCodes.isEmpty()) {
return StructOrError.fromStruct(
RetryPolicy.create(
maxAttempts, retryableStatusCodes, initialBackoff, maxBackoff,
/* perAttemptRecvTimeout= */ null));
}
return null;
return StructOrError.fromStruct(
RetryPolicy.create(
maxAttempts, retryableStatusCodes, initialBackoff, maxBackoff,
/* perAttemptRecvTimeout= */ null));
}
@VisibleForTesting

View File

@ -182,13 +182,14 @@ final class XdsNameResolver extends NameResolver {
@VisibleForTesting
static Map<String, ?> generateServiceConfigWithMethodConfig(
@Nullable Long timeoutNano, @Nullable RetryPolicy retryPolicy) {
if (timeoutNano == null && retryPolicy == null) {
if (timeoutNano == null
&& (retryPolicy == null || retryPolicy.retryableStatusCodes().isEmpty())) {
return Collections.emptyMap();
}
ImmutableMap.Builder<String, Object> methodConfig = ImmutableMap.builder();
methodConfig.put(
"name", Collections.singletonList(Collections.emptyMap()));
if (retryPolicy != null) {
if (retryPolicy != null && !retryPolicy.retryableStatusCodes().isEmpty()) {
ImmutableMap.Builder<String, Object> rawRetryPolicy = ImmutableMap.builder();
rawRetryPolicy.put("maxAttempts", (double) retryPolicy.maxAttempts());
rawRetryPolicy.put("initialBackoff", Durations.toString(retryPolicy.initialBackoff()));

View File

@ -552,7 +552,8 @@ public class ClientXdsClientDataTest {
.setRetryPolicy(builder.build())
.build();
struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
assertThat(struct.getStruct().retryPolicy()).isNull();
assertThat(struct.getStruct().retryPolicy()).isNotNull();
assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()).isEmpty();
// base_interval unset
builder

View File

@ -988,6 +988,8 @@ public class XdsNameResolverTest {
RetryPolicy retryPolicy = RetryPolicy.create(
4, ImmutableList.of(Code.UNAVAILABLE, Code.CANCELLED), Durations.fromMillis(100),
Durations.fromMillis(200), null);
RetryPolicy retryPolicyWithEmptyStatusCodes = RetryPolicy.create(
4, ImmutableList.<Code>of(), Durations.fromMillis(100), Durations.fromMillis(200), null);
// timeout only
String expectedServiceConfigJson = "{\n"
@ -1001,6 +1003,11 @@ public class XdsNameResolverTest {
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(timeoutNano, null))
.isEqualTo(expectedServiceConfig);
// timeout and retry with empty retriable status codes
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(
timeoutNano, retryPolicyWithEmptyStatusCodes))
.isEqualTo(expectedServiceConfig);
// retry only
expectedServiceConfigJson = "{\n"
+ " \"methodConfig\": [{\n"
@ -1021,6 +1028,7 @@ public class XdsNameResolverTest {
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(null, retryPolicy))
.isEqualTo(expectedServiceConfig);
// timeout and retry
expectedServiceConfigJson = "{\n"
+ " \"methodConfig\": [{\n"
@ -1043,12 +1051,16 @@ public class XdsNameResolverTest {
.isEqualTo(expectedServiceConfig);
// no timeout and no retry
// timeout and retry
expectedServiceConfigJson = "{}";
expectedServiceConfig =
(Map<String, ?>) JsonParser.parse(expectedServiceConfigJson);
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(null, null))
.isEqualTo(expectedServiceConfig);
// retry with emtry retriable status codes only
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(
null, retryPolicyWithEmptyStatusCodes))
.isEqualTo(expectedServiceConfig);
}
@Test