Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#10693] Add enable option for grpc client reties #10732

Merged
merged 1 commit into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019 NAVER Corp.
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@
package com.navercorp.pinpoint.grpc.client;

import com.navercorp.pinpoint.grpc.client.config.ClientOption;
import com.navercorp.pinpoint.grpc.client.config.ClientRetryOption;
import io.grpc.ClientInterceptor;
import io.grpc.NameResolverProvider;
import io.netty.handler.ssl.SslContext;
Expand All @@ -40,6 +41,8 @@ public interface ChannelFactoryBuilder {

void setSslContext(SslContext sslContext);

void setClientRetryOption(ClientRetryOption clientRetryOption);

void setNameResolverProvider(NameResolverProvider nameResolverProvider);

ChannelFactory build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019 NAVER Corp.
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@
import com.navercorp.pinpoint.grpc.ChannelTypeEnum;
import com.navercorp.pinpoint.grpc.ExecutorUtils;
import com.navercorp.pinpoint.grpc.client.config.ClientOption;
import com.navercorp.pinpoint.grpc.client.config.ClientRetryOption;
import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
Expand Down Expand Up @@ -63,6 +64,9 @@
// nullable
private final SslContext sslContext;

// nullable
private final ClientRetryOption clientRetryOption;

private final List<ClientInterceptor> clientInterceptorList;
private final NameResolverProvider nameResolverProvider;

Expand All @@ -78,7 +82,8 @@
NameResolverProvider nameResolverProvider,
ClientOption clientOption,
List<ClientInterceptor> clientInterceptorList,
SslContext sslContext) {
SslContext sslContext,
ClientRetryOption clientRetryOption) {
this.factoryName = Objects.requireNonNull(factoryName, "factoryName");
this.executorQueueSize = executorQueueSize;
this.headerFactory = Objects.requireNonNull(headerFactory, "headerFactory");
Expand All @@ -90,6 +95,8 @@
this.clientInterceptorList = new ArrayList<>(clientInterceptorList);
// nullable
this.sslContext = sslContext;
// nullable
this.clientRetryOption = clientRetryOption;


ChannelType channelType = getChannelType();
Expand Down Expand Up @@ -157,6 +164,12 @@
channelBuilder.negotiationType(NegotiationType.TLS);
}

// RetryOption
if (clientRetryOption != null) {
setupRetryOption(channelBuilder);

Check warning on line 169 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java#L169

Added line #L169 was not covered by tests
}


channelBuilder.maxTraceEvents(clientOption.getMaxTraceEvent());

return channelBuilder.build();
Expand Down Expand Up @@ -210,6 +223,18 @@
}
}

private void setupRetryOption(final NettyChannelBuilder channelBuilder) {
channelBuilder.enableRetry();
channelBuilder.retryBufferSize(clientRetryOption.getRetryBufferSize());
channelBuilder.perRpcBufferLimit(clientRetryOption.getPerRpcBufferLimit());

Check warning on line 229 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java#L227-L229

Added lines #L227 - L229 were not covered by tests

//channelBuilder.disableServiceConfigLookUp();
channelBuilder.defaultServiceConfig(clientRetryOption.getRetryServiceConfig());

Check warning on line 232 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java#L232

Added line #L232 was not covered by tests
if (logger.isDebugEnabled()) {
logger.debug("Set clientRetryOption {}. name={}", clientRetryOption, factoryName);

Check warning on line 234 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java#L234

Added line #L234 was not covered by tests
}
}

Check warning on line 236 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactory.java#L236

Added line #L236 was not covered by tests

@Override
public void close() {
final Future<?> future = eventLoopGroup.shutdownGracefully();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019 NAVER Corp.
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import com.navercorp.pinpoint.common.util.Assert;
import com.navercorp.pinpoint.grpc.client.config.ClientOption;
import com.navercorp.pinpoint.grpc.client.config.ClientRetryOption;
import io.grpc.ClientInterceptor;
import io.grpc.NameResolverProvider;
import io.netty.handler.ssl.SslContext;
Expand All @@ -41,6 +42,7 @@

private ClientOption clientOption;
private SslContext sslContext;
private ClientRetryOption clientRetryOption;

private final LinkedList<ClientInterceptor> clientInterceptorList = new LinkedList<>();
private NameResolverProvider nameResolverProvider;
Expand Down Expand Up @@ -82,6 +84,11 @@
this.sslContext = sslContext;
}

@Override
public void setClientRetryOption(ClientRetryOption clientRetryOption) {
this.clientRetryOption = clientRetryOption;
}

Check warning on line 90 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactoryBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/DefaultChannelFactoryBuilder.java#L89-L90

Added lines #L89 - L90 were not covered by tests

@Override
public void setNameResolverProvider(NameResolverProvider nameResolverProvider) {
this.nameResolverProvider = Objects.requireNonNull(nameResolverProvider, "nameResolverProvider");
Expand All @@ -95,6 +102,7 @@

return new DefaultChannelFactory(factoryName, executorQueueSize,
headerFactory, nameResolverProvider,
clientOption, clientInterceptorList, sslContext);
clientOption, clientInterceptorList,
sslContext, clientRetryOption);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.grpc.client.config;

import java.util.Map;

public class ClientRetryOption {

private final long retryBufferSize;
private final long perRpcBufferLimit;
private final Map<String, ?> retryServiceConfig;

public ClientRetryOption(long retryBufferSize, long perRpcBufferLimit, Map<String, ?> retryServiceConfig) {
this.retryBufferSize = retryBufferSize;
this.perRpcBufferLimit = perRpcBufferLimit;
this.retryServiceConfig = retryServiceConfig;
}

Check warning on line 31 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java#L27-L31

Added lines #L27 - L31 were not covered by tests

public long getRetryBufferSize() {
return retryBufferSize;

Check warning on line 34 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java#L34

Added line #L34 was not covered by tests
}

public long getPerRpcBufferLimit() {
return perRpcBufferLimit;

Check warning on line 38 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java#L38

Added line #L38 was not covered by tests
}

public Map<String, ?> getRetryServiceConfig() {
return retryServiceConfig;

Check warning on line 42 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java#L42

Added line #L42 was not covered by tests
}

@Override
public String toString() {
return "ClientRetryOption{" +

Check warning on line 47 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/config/ClientRetryOption.java#L47

Added line #L47 was not covered by tests
"retryBufferSize=" + retryBufferSize +
", perRpcBufferLimit=" + perRpcBufferLimit +
", retryServiceConfig=" + retryServiceConfig +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.grpc.client.retry;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class HedgingServiceConfigBuilder implements ServiceConfigBuilder {

public static final int DEFAULT_MAX_ATTEMPTS = 3;
public static final long DEFAULT_HEDGING_DELAY_MILLIS = 1000L;

private double maxAttempts = DEFAULT_MAX_ATTEMPTS; //Required. Must be two or greater
private String hedgingDelay = millisToString(DEFAULT_HEDGING_DELAY_MILLIS); //Required. Long decimal with "s" appended
private List<String> nonFatalStatusCodes; //Optional (eg. [14], ["UNAVAILABLE"] or ["unavailable"])

@Override
public Map<String, ?> buildMetadataConfig() {
Map<String, Object> methodConfig = new LinkedHashMap<>();
addMetadataService(methodConfig);
addHedgingPolicy(methodConfig);
return Collections.singletonMap("methodConfig", Collections.singletonList(methodConfig));
}

private void addMetadataService(Map<String, Object> methodConfig) {
Map<String, Object> service = Collections.singletonMap("service", METADATA_SERVICE);
methodConfig.put("name", Collections.singletonList(service));
}

private void addHedgingPolicy(Map<String, Object> methodConfig) {
Map<String, Object> retryPolicy = new LinkedHashMap<>();
retryPolicy.put("maxAttempts", maxAttempts);
retryPolicy.put("hedgingDelay", hedgingDelay);
if (nonFatalStatusCodes != null && !nonFatalStatusCodes.isEmpty()) {
retryPolicy.put("nonFatalStatusCodes", nonFatalStatusCodes);

Check warning on line 51 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java#L51

Added line #L51 was not covered by tests
}

methodConfig.put("hedgingPolicy", retryPolicy);
}


public void setMaxAttempts(int maxAttempts) {
if (maxAttempts >= 2) {
this.maxAttempts = maxAttempts;

Check warning on line 60 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java#L60

Added line #L60 was not covered by tests
}
}

Check warning on line 62 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java#L62

Added line #L62 was not covered by tests

public void setHedgingDelayMillis(long hedgingDelay) {
this.hedgingDelay = millisToString(hedgingDelay);
}

Check warning on line 66 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java#L65-L66

Added lines #L65 - L66 were not covered by tests

public void setNonFatalStatusCodes(List<String> nonFatalStatusCodes) {
this.nonFatalStatusCodes = nonFatalStatusCodes;
}

Check warning on line 70 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/HedgingServiceConfigBuilder.java#L69-L70

Added lines #L69 - L70 were not covered by tests

public String millisToString(long value) {
return value / 1000.0 + "s";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.grpc.client.retry;

import io.grpc.Status;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class RetryServiceConfigBuilder implements ServiceConfigBuilder {

public static final double DEFAULT_MAX_ATTEMPTS = 3.0;
public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 1000L;
public static final long DEFAULT_MAX_BACKOFF_MILLIS = 4000L;
public static final double DEFAULT_BACKOFF_MULTIPLIER = 2.0;
public static final List<String> DEFAULT_RETRYABLE_STATUS_CODES = Collections.singletonList(Status.Code.UNAVAILABLE.name());

private Double maxAttempts = DEFAULT_MAX_ATTEMPTS; //Required. Must be two or greater
private String initialBackoff = millisToString(DEFAULT_INITIAL_BACKOFF_MILLIS); //Required. Long decimal with "s" appended
private String maxBackoff = millisToString(DEFAULT_MAX_BACKOFF_MILLIS); //Required. Long decimal with "s" appended
private Double backoffMultiplier = DEFAULT_BACKOFF_MULTIPLIER; //Required. Must be greater than zero.
private List<String> retryableStatusCodes; //Required and must be non-empty (eg. [14], ["UNAVAILABLE"] or ["unavailable"])

@Override
public Map<String, ?> buildMetadataConfig() {
Map<String, Object> methodConfig = new LinkedHashMap<>();
addMetadataService(methodConfig);
addRetryPolicy(methodConfig);
return Collections.singletonMap("methodConfig", Collections.singletonList(methodConfig));
}

private void addMetadataService(Map<String, Object> methodConfig) {
Map<String, Object> service = Collections.singletonMap("service", METADATA_SERVICE);
methodConfig.put("name", Collections.singletonList(service));
}

private void addRetryPolicy(Map<String, Object> methodConfig) {
Map<String, Object> retryPolicy = new LinkedHashMap<>();
retryPolicy.put("maxAttempts", maxAttempts);
retryPolicy.put("initialBackoff", initialBackoff);
retryPolicy.put("maxBackoff", maxBackoff);
retryPolicy.put("backoffMultiplier", backoffMultiplier);
if (retryableStatusCodes == null || retryableStatusCodes.isEmpty()) {
retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES;
}
retryPolicy.put("retryableStatusCodes", retryableStatusCodes);

methodConfig.put("retryPolicy", retryPolicy);
}

public void setMaxAttempts(double maxAttempts) {
if (maxAttempts >= 2) {
this.maxAttempts = maxAttempts;

Check warning on line 69 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L69

Added line #L69 was not covered by tests
}
}

Check warning on line 71 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L71

Added line #L71 was not covered by tests

public void setInitialBackOff(long initialBackoff) {
this.initialBackoff = millisToString(initialBackoff);
}

Check warning on line 75 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L74-L75

Added lines #L74 - L75 were not covered by tests

public void setMaxBackoff(long maxBackoff) {
this.maxBackoff = millisToString(maxBackoff);
}

Check warning on line 79 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L78-L79

Added lines #L78 - L79 were not covered by tests

public void setBackoffMultiplier(double backoffMultiplier) {
this.backoffMultiplier = backoffMultiplier;
}

Check warning on line 83 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L82-L83

Added lines #L82 - L83 were not covered by tests

public void setRetryableStatusCodes(List<String> retryableStatusCodes) {
this.retryableStatusCodes = retryableStatusCodes;
}

Check warning on line 87 in grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java

View check run for this annotation

Codecov / codecov/patch

grpc/src/main/java/com/navercorp/pinpoint/grpc/client/retry/RetryServiceConfigBuilder.java#L86-L87

Added lines #L86 - L87 were not covered by tests

public String millisToString(long value) {
return value / 1000.0 + "s";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.grpc.client.retry;

import java.util.Map;

public interface ServiceConfigBuilder {

String METADATA_SERVICE = "v1.metadata";

Map<String, ?> buildMetadataConfig();

}
Loading
Loading