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

新增对ServiceConfig配置的支持 #574

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -22,10 +22,7 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
Expand All @@ -34,6 +31,7 @@
import javax.annotation.PreDestroy;
import javax.annotation.concurrent.GuardedBy;

import net.devh.boot.grpc.client.config.*;
import org.springframework.util.unit.DataSize;

import com.google.common.collect.Lists;
Expand All @@ -45,10 +43,7 @@
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
import net.devh.boot.grpc.client.config.GrpcChannelProperties.Security;
import net.devh.boot.grpc.client.config.GrpcChannelsProperties;
import net.devh.boot.grpc.client.config.NegotiationType;
import net.devh.boot.grpc.client.interceptor.GlobalClientInterceptorRegistry;

/**
Expand Down Expand Up @@ -168,11 +163,59 @@ protected void configure(final T builder, final String name) {
configureSecurity(builder, name);
configureLimits(builder, name);
configureCompression(builder, name);
configureRetryEnabled(builder, name);
for (final GrpcChannelConfigurer channelConfigurer : this.channelConfigurers) {
channelConfigurer.accept(builder, name);
}
}

/**
* Configures the retry options that should be used by the channel.
*
* @param builder The channel builder to configure.
* @param name The name of the client to configure.
*/
protected void configureRetryEnabled(final T builder, final String name) {
final GrpcChannelProperties properties = getPropertiesFor(name);
if (properties.isRetryEnabled()) {
builder.enableRetry();
//build retry policy by default service config
builder.defaultServiceConfig(buildDefaultServiceConfig(properties));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default service config might be used outside of the retry logic.
So it might be neccessary to move it "elsewhere".

}
}

/**
* build service config object
*
* @param properties The properties of
*/
protected Map<String, Object> buildDefaultServiceConfig(final GrpcChannelProperties properties) {
Map<String, Object> serviceConfig = new HashMap<>();
List<MethodConfig> methodConfigList = properties.getMethodConfig();
if (null == methodConfigList || methodConfigList.isEmpty()) {
return serviceConfig;
}
List<Map<String, Object>> methodConfigJsonList = new ArrayList<>();
methodConfigList.forEach(methodConfig -> {
Map<String, Object> methodConfigMap = new HashMap<>();
//set method config
List<NameConfig> nameConfigList = methodConfig.getName();
if (null != nameConfigList && !nameConfigList.isEmpty()) {
List<Map<String, Object>> list = new ArrayList<>();
nameConfigList.forEach(nameConfig -> list.add(nameConfig.buildMap()));
methodConfigMap.put("name", list);
}
//set retry policy
RetryPolicyConfig retryConfig = methodConfig.getRetryPolicy();
if (retryConfig != null) {
methodConfigMap.put("retryPolicy", retryConfig.buildMap());
}
methodConfigJsonList.add(methodConfigMap);
});
serviceConfig.put("methodConfig", methodConfigJsonList);
return serviceConfig;
}

/**
* Configures the keep alive options that should be used by the channel.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.net.URI;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -421,6 +422,47 @@ public void setImmediateConnectTimeout(final Duration immediateConnectTimeout) {

// --------------------------------------------------

private Boolean retryEnabled;
private static final boolean DEFAULT_RETRY_ENABLED = false;

/**
* Gets whether retry should be enabled.
*
* @return True, if retry should be enabled. False otherwise.
* @see #setRetryEnabled(Boolean)
*/
public boolean isRetryEnabled() {
return this.retryEnabled == null ? DEFAULT_RETRY_ENABLED : this.retryEnabled;
}

/**
* Set Retry enable
*
* @param retryEnabled Whether retry enabled or null to use the fallback.
* @see ManagedChannelBuilder#enableRetry()
*/
public void setRetryEnabled(final Boolean retryEnabled) {
this.retryEnabled = retryEnabled;
}

public Boolean getRetryEnabled() {
return retryEnabled;
}

// --------------------------------------------------

private List<MethodConfig> methodConfig;

public List<MethodConfig> getMethodConfig() {
return methodConfig;
}

public void setMethodConfig(List<MethodConfig> methodConfig) {
this.methodConfig = methodConfig;
}

// --------------------------------------------------

private final Security security = new Security();

/**
Expand Down Expand Up @@ -475,6 +517,19 @@ public void copyDefaultsFrom(final GrpcChannelProperties config) {
if (this.immediateConnectTimeout == null) {
this.immediateConnectTimeout = config.immediateConnectTimeout;
}
if (this.retryEnabled == null) {
this.retryEnabled = config.retryEnabled;
}
if (this.methodConfig == null || this.methodConfig.isEmpty()) {
this.methodConfig = new ArrayList<>();
if (config.getMethodConfig() != null && !config.getMethodConfig().isEmpty()) {
config.getMethodConfig().forEach(cf -> {
MethodConfig newMethodConfig = new MethodConfig();
newMethodConfig.copyDefaultsFrom(cf);
this.methodConfig.add(newMethodConfig);
});
}
}
this.security.copyDefaultsFrom(config.security);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package net.devh.boot.grpc.client.config;

import lombok.EqualsAndHashCode;
import lombok.ToString;

import java.util.ArrayList;
import java.util.List;

/**
* @Title 方法配置信息实体, 请参考如下链接:
* https://github.com/grpc/proposal/blob/37e658b12f1684f29b3acca04f0167b84d502876/A6-client-retries.md#grpc-retry-design
* https://github.com/grpc/grpc/blob/master/doc/service_config.md
* @Description MethodConfig
* @Program spring-cloud-tcl-starter
* @Author wushengju
* @Version 1.0
* @Date 2021-08-10 13:38
* @Copyright Copyright (c) 2021 TCL Inc. All rights reserved
**/
@ToString
@EqualsAndHashCode
public class MethodConfig {
/**
* retry policy config
*/
private RetryPolicyConfig retryPolicy;
/**
* name for list
*/
private List<NameConfig> name;

public RetryPolicyConfig getRetryPolicy() {
return retryPolicy;
}

public void setRetryPolicy(RetryPolicyConfig retryPolicy) {
this.retryPolicy = retryPolicy;
}

public List<NameConfig> getName() {
return name;
}

public void setName(List<NameConfig> name) {
this.name = name;
}

public void copyDefaultsFrom(final MethodConfig config) {
if (this == config) {
return;
}
this.retryPolicy.copyDefaultsFrom(config.retryPolicy);
if (this.name == null || this.name.isEmpty()) {
if (config.getName() != null && !config.getName().isEmpty()) {
this.name = new ArrayList<>();
config.getName().forEach(nameConfig -> {
NameConfig newConfig = new NameConfig();
newConfig.copyDefaultsFrom(nameConfig);
this.name.add(newConfig);
});
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package net.devh.boot.grpc.client.config;

import lombok.EqualsAndHashCode;
import lombok.ToString;

import java.util.HashMap;
import java.util.Map;

/**
* @Title method config
* @Description MethodConfig
* @Program spring-cloud-tcl-starter
* @Author wushengju
* @Version 1.0
* @Date 2021-08-10 10:55
* @Copyright Copyright (c) 2021 TCL Inc. All rights reserved
**/
@ToString
@EqualsAndHashCode
public class NameConfig {
/**
* the service name which defined in xx.proto
*/
private String service;
/**
* the method name which you will call
*/
private String method;

public Map<String, Object> buildMap() {
Map<String, Object> map = new HashMap<>();
map.put("service", this.getService());
map.put("method", this.getMethod());
return map;
}

public void copyDefaultsFrom(final NameConfig config) {
if (this == config) {
return;
}
if (this.service == null) {
this.service = config.service;
}
if (this.method == null) {
this.method = config.method;
}
}
public String getService() {
return service;
}

public void setService(String service) {
this.service = service;
}

public String getMethod() {
return method;
}

public void setMethod(String method) {
this.method = method;
}
}
Loading