Search in sources :

Example 1 with RetryPolicy

use of io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy in project grpc-java by grpc.

the class XdsNameResolverTest method retryPolicyInPerMethodConfigGeneratedByResolverIsValid.

@Test
public void retryPolicyInPerMethodConfigGeneratedByResolverIsValid() {
    ServiceConfigParser realParser = new ScParser(true, 5, 5, new AutoConfiguredLoadBalancerFactory("pick-first"));
    resolver = new XdsNameResolver(null, AUTHORITY, realParser, syncContext, scheduler, xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
    resolver.start(mockListener);
    FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
    RetryPolicy retryPolicy = RetryPolicy.create(4, ImmutableList.of(Code.UNAVAILABLE), Durations.fromMillis(100), Durations.fromMillis(200), null);
    xdsClient.deliverLdsUpdate(Collections.singletonList(Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()), RouteAction.forCluster(cluster1, Collections.<HashPolicy>emptyList(), null, retryPolicy), ImmutableMap.<String, FilterConfig>of())));
    verify(mockListener).onResult(resolutionResultCaptor.capture());
    ResolutionResult result = resolutionResultCaptor.getValue();
    InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
    Result selectResult = configSelector.selectConfig(new PickSubchannelArgsImpl(call1.methodDescriptor, new Metadata(), CallOptions.DEFAULT));
    Object config = selectResult.getConfig();
    // Purely validating the data (io.grpc.internal.RetryPolicy).
    // However, there's no public accessor methods the data object.
    assertThat(config.getClass().getName()).isEqualTo("io.grpc.internal.ManagedChannelServiceConfig");
    assertThat(config.toString()).contains(MoreObjects.toStringHelper("RetryPolicy").add("maxAttempts", 4).add("initialBackoffNanos", TimeUnit.MILLISECONDS.toNanos(100)).add("maxBackoffNanos", TimeUnit.MILLISECONDS.toNanos(200)).add("backoffMultiplier", 2D).add("perAttemptRecvTimeoutNanos", null).add("retryableStatusCodes", ImmutableList.of(Code.UNAVAILABLE)).toString());
}
Also used : ResolutionResult(io.grpc.NameResolver.ResolutionResult) Metadata(io.grpc.Metadata) ResolutionResult(io.grpc.NameResolver.ResolutionResult) Result(io.grpc.InternalConfigSelector.Result) AutoConfiguredLoadBalancerFactory(io.grpc.internal.AutoConfiguredLoadBalancerFactory) PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) ScParser(io.grpc.internal.ScParser) InternalConfigSelector(io.grpc.InternalConfigSelector) HashPolicy(io.grpc.xds.VirtualHost.Route.RouteAction.HashPolicy) ServiceConfigParser(io.grpc.NameResolver.ServiceConfigParser) RetryPolicy(io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy) Test(org.junit.Test)

Example 2 with RetryPolicy

use of io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy in project grpc-java by grpc.

the class XdsNameResolverTest method generateServiceConfig_forPerMethodConfig.

@SuppressWarnings("unchecked")
@Test
public void generateServiceConfig_forPerMethodConfig() throws IOException {
    // 1.0000000001s
    long timeoutNano = TimeUnit.SECONDS.toNanos(1L) + 1L;
    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" + "  \"methodConfig\": [{\n" + "    \"name\": [ {} ],\n" + "    \"timeout\": \"1.000000001s\"\n" + "  }]\n" + "}";
    Map<String, ?> expectedServiceConfig = (Map<String, ?>) JsonParser.parse(expectedServiceConfigJson);
    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" + "    \"name\": [ {} ],\n" + "    \"retryPolicy\": {\n" + "      \"maxAttempts\" : 4,\n" + "      \"initialBackoff\": \"0.100s\",\n" + "      \"maxBackoff\": \"0.200s\",\n" + "      \"backoffMultiplier\": 2,\n" + "      \"retryableStatusCodes\": [\n" + "        \"UNAVAILABLE\", \"CANCELLED\"\n" + "      ]\n" + "    }\n" + "  }]\n" + "}";
    expectedServiceConfig = (Map<String, ?>) JsonParser.parse(expectedServiceConfigJson);
    assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(null, retryPolicy)).isEqualTo(expectedServiceConfig);
    // timeout and retry
    expectedServiceConfigJson = "{\n" + "  \"methodConfig\": [{\n" + "    \"name\": [ {} ],\n" + "    \"retryPolicy\": {\n" + "      \"maxAttempts\" : 4,\n" + "      \"initialBackoff\": \"0.100s\",\n" + "      \"maxBackoff\": \"0.200s\",\n" + "      \"backoffMultiplier\": 2,\n" + "      \"retryableStatusCodes\": [\n" + "        \"UNAVAILABLE\", \"CANCELLED\"\n" + "      ]\n" + "    },\n" + "    \"timeout\": \"1.000000001s\"\n" + "  }]\n" + "}";
    expectedServiceConfig = (Map<String, ?>) JsonParser.parse(expectedServiceConfigJson);
    assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(timeoutNano, retryPolicy)).isEqualTo(expectedServiceConfig);
    // no timeout and no 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);
}
Also used : RetryPolicy(io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) Test(org.junit.Test)

Example 3 with RetryPolicy

use of io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy in project grpc-java by grpc.

the class ClientXdsClient method parseRouteAction.

/**
 * Parses the RouteAction config. The returned result may contain a (parsed form)
 * {@link RouteAction} or an error message. Returns {@code null} if the RouteAction
 * should be ignored.
 */
@VisibleForTesting
@Nullable
static StructOrError<RouteAction> parseRouteAction(io.envoyproxy.envoy.config.route.v3.RouteAction proto, FilterRegistry filterRegistry, boolean parseHttpFilter, Map<String, PluginConfig> pluginConfigMap) {
    Long timeoutNano = null;
    if (proto.hasMaxStreamDuration()) {
        io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration maxStreamDuration = proto.getMaxStreamDuration();
        if (maxStreamDuration.hasGrpcTimeoutHeaderMax()) {
            timeoutNano = Durations.toNanos(maxStreamDuration.getGrpcTimeoutHeaderMax());
        } else if (maxStreamDuration.hasMaxStreamDuration()) {
            timeoutNano = Durations.toNanos(maxStreamDuration.getMaxStreamDuration());
        }
    }
    RetryPolicy retryPolicy = null;
    if (enableRetry && proto.hasRetryPolicy()) {
        StructOrError<RetryPolicy> retryPolicyOrError = parseRetryPolicy(proto.getRetryPolicy());
        if (retryPolicyOrError != null) {
            if (retryPolicyOrError.errorDetail != null) {
                return StructOrError.fromError(retryPolicyOrError.errorDetail);
            }
            retryPolicy = retryPolicyOrError.struct;
        }
    }
    List<HashPolicy> hashPolicies = new ArrayList<>();
    for (io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy config : proto.getHashPolicyList()) {
        HashPolicy policy = null;
        boolean terminal = config.getTerminal();
        switch(config.getPolicySpecifierCase()) {
            case HEADER:
                io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.Header headerCfg = config.getHeader();
                Pattern regEx = null;
                String regExSubstitute = null;
                if (headerCfg.hasRegexRewrite() && headerCfg.getRegexRewrite().hasPattern() && headerCfg.getRegexRewrite().getPattern().hasGoogleRe2()) {
                    regEx = Pattern.compile(headerCfg.getRegexRewrite().getPattern().getRegex());
                    regExSubstitute = headerCfg.getRegexRewrite().getSubstitution();
                }
                policy = HashPolicy.forHeader(terminal, headerCfg.getHeaderName(), regEx, regExSubstitute);
                break;
            case FILTER_STATE:
                if (config.getFilterState().getKey().equals(HASH_POLICY_FILTER_STATE_KEY)) {
                    policy = HashPolicy.forChannelId(terminal);
                }
                break;
            default:
        }
        if (policy != null) {
            hashPolicies.add(policy);
        }
    }
    switch(proto.getClusterSpecifierCase()) {
        case CLUSTER:
            return StructOrError.fromStruct(RouteAction.forCluster(proto.getCluster(), hashPolicies, timeoutNano, retryPolicy));
        case CLUSTER_HEADER:
            return null;
        case WEIGHTED_CLUSTERS:
            List<io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight> clusterWeights = proto.getWeightedClusters().getClustersList();
            if (clusterWeights.isEmpty()) {
                return StructOrError.fromError("No cluster found in weighted cluster list");
            }
            List<ClusterWeight> weightedClusters = new ArrayList<>();
            for (io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight clusterWeight : clusterWeights) {
                StructOrError<ClusterWeight> clusterWeightOrError = parseClusterWeight(clusterWeight, filterRegistry, parseHttpFilter);
                if (clusterWeightOrError.getErrorDetail() != null) {
                    return StructOrError.fromError("RouteAction contains invalid ClusterWeight: " + clusterWeightOrError.getErrorDetail());
                }
                weightedClusters.add(clusterWeightOrError.getStruct());
            }
            // TODO(chengyuanzhang): validate if the sum of weights equals to total weight.
            return StructOrError.fromStruct(RouteAction.forWeightedClusters(weightedClusters, hashPolicies, timeoutNano, retryPolicy));
        case CLUSTER_SPECIFIER_PLUGIN:
            if (enableRouteLookup) {
                String pluginName = proto.getClusterSpecifierPlugin();
                PluginConfig pluginConfig = pluginConfigMap.get(pluginName);
                if (pluginConfig == null) {
                    return StructOrError.fromError("ClusterSpecifierPlugin for [" + pluginName + "] not found");
                }
                NamedPluginConfig namedPluginConfig = NamedPluginConfig.create(pluginName, pluginConfig);
                return StructOrError.fromStruct(RouteAction.forClusterSpecifierPlugin(namedPluginConfig, hashPolicies, timeoutNano, retryPolicy));
            } else {
                return StructOrError.fromError("Support for ClusterSpecifierPlugin not enabled");
            }
        case CLUSTERSPECIFIER_NOT_SET:
        default:
            return StructOrError.fromError("Unknown cluster specifier: " + proto.getClusterSpecifierCase());
    }
}
Also used : ArrayList(java.util.ArrayList) HashPolicy(io.grpc.xds.VirtualHost.Route.RouteAction.HashPolicy) Pattern(com.google.re2j.Pattern) ClusterWeight(io.grpc.xds.VirtualHost.Route.RouteAction.ClusterWeight) NamedPluginConfig(io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig) RouteAction(io.grpc.xds.VirtualHost.Route.RouteAction) NamedPluginConfig(io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig) PluginConfig(io.grpc.xds.ClusterSpecifierPlugin.PluginConfig) RetryPolicy(io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Nullable(javax.annotation.Nullable)

Aggregations

RetryPolicy (io.grpc.xds.VirtualHost.Route.RouteAction.RetryPolicy)3 HashPolicy (io.grpc.xds.VirtualHost.Route.RouteAction.HashPolicy)2 Test (org.junit.Test)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 Pattern (com.google.re2j.Pattern)1 InternalConfigSelector (io.grpc.InternalConfigSelector)1 Result (io.grpc.InternalConfigSelector.Result)1 Metadata (io.grpc.Metadata)1 ResolutionResult (io.grpc.NameResolver.ResolutionResult)1 ServiceConfigParser (io.grpc.NameResolver.ServiceConfigParser)1 AutoConfiguredLoadBalancerFactory (io.grpc.internal.AutoConfiguredLoadBalancerFactory)1 PickSubchannelArgsImpl (io.grpc.internal.PickSubchannelArgsImpl)1 ScParser (io.grpc.internal.ScParser)1 NamedPluginConfig (io.grpc.xds.ClusterSpecifierPlugin.NamedPluginConfig)1 PluginConfig (io.grpc.xds.ClusterSpecifierPlugin.PluginConfig)1 RouteAction (io.grpc.xds.VirtualHost.Route.RouteAction)1 ClusterWeight (io.grpc.xds.VirtualHost.Route.RouteAction.ClusterWeight)1 ArrayList (java.util.ArrayList)1 Map (java.util.Map)1