From f22f32aca675bdb8b86723ea78a532f7937f01f2 Mon Sep 17 00:00:00 2001 From: Haotian Zhang <928016560@qq.com> Date: Wed, 11 May 2022 14:06:46 +0800 Subject: [PATCH] fix:fix routes of gateway doesn't refresh bug. (#158) * fix:fix routes of gateway doesn't refresh bug. * docs:update CHANGELOG.md. --- CHANGELOG.md | 6 +- changes/changes-1.4.0.md | 8 +++ pom.xml | 2 +- .../polaris/DiscoveryConfigModifier.java | 9 +++ .../polaris/PolarisDiscoveryProperties.java | 13 ++++ .../discovery/PolarisDiscoveryHandler.java | 8 +++ .../PolarisServiceChangeListener.java | 62 +++++++++++++++++++ .../registry/PolarisServiceRegistry.java | 10 ++- ...larisServiceRegistryAutoConfiguration.java | 13 ++-- ...itional-spring-configuration-metadata.json | 6 ++ spring-cloud-tencent-dependencies/pom.xml | 2 +- .../src/main/resources/bootstrap.yml | 49 ++++++++++++--- src/checkstyle/checkstyle-suppressions.xml | 1 + 13 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 changes/changes-1.4.0.md create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceChangeListener.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 2784188a0..6a9771825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,4 @@ # Change Log --- -- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/128) -- [Feature: Optimize config server address](https://github.com/Tencent/spring-cloud-tencent/pull/130) -- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/131) -- [feat:refactor loadbalancer module as a basic module for router and circuit breaker.](https://github.com/Tencent/spring-cloud-tencent/pull/136) -- [feat:enable distribute rate limit](https://github.com/Tencent/spring-cloud-tencent/pull/139) \ No newline at end of file +- [fix:fix routes of gateway doesn't refresh bug.](https://github.com/Tencent/spring-cloud-tencent/pull/158) \ No newline at end of file diff --git a/changes/changes-1.4.0.md b/changes/changes-1.4.0.md new file mode 100644 index 000000000..2784188a0 --- /dev/null +++ b/changes/changes-1.4.0.md @@ -0,0 +1,8 @@ +# Change Log +--- + +- [Feature: Support custom rate limit reject response info](https://github.com/Tencent/spring-cloud-tencent/pull/128) +- [Feature: Optimize config server address](https://github.com/Tencent/spring-cloud-tencent/pull/130) +- [Feature: Remove spring-javaformat-maven-plugin](https://github.com/Tencent/spring-cloud-tencent/pull/131) +- [feat:refactor loadbalancer module as a basic module for router and circuit breaker.](https://github.com/Tencent/spring-cloud-tencent/pull/136) +- [feat:enable distribute rate limit](https://github.com/Tencent/spring-cloud-tencent/pull/139) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6feeda61c..1bd9b8b05 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ - 1.4.1-Hoxton.SR9 + 1.4.2-Hoxton.SR9-SNAPSHOT Hoxton.SR9 diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java index a52a6dd4b..67690ef24 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/DiscoveryConfigModifier.java @@ -24,6 +24,8 @@ import com.tencent.polaris.api.config.consumer.ServiceRouterConfig; import com.tencent.polaris.factory.config.ConfigurationImpl; import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig; +import org.springframework.beans.factory.annotation.Autowired; + /** * Spring Cloud Tencent config Override polaris config. * @@ -31,6 +33,9 @@ import com.tencent.polaris.plugins.router.healthy.RecoverRouterConfig; */ public class DiscoveryConfigModifier implements PolarisConfigModifier { + @Autowired + private PolarisDiscoveryProperties polarisDiscoveryProperties; + @Override public void modify(ConfigurationImpl configuration) { // Set excludeCircuitBreakInstances to false @@ -41,6 +46,10 @@ public class DiscoveryConfigModifier implements PolarisConfigModifier { // Update modified config to source properties configuration.getConsumer().getServiceRouter() .setPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, recoverRouterConfig); + + // Set ServiceRefreshInterval + configuration.getConsumer().getLocalCache() + .setServiceListRefreshInterval(polarisDiscoveryProperties.getServiceListRefreshInterval()); } @Override diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java index 37b0ad45f..77483b360 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java @@ -105,6 +105,11 @@ public class PolarisDiscoveryProperties { @Value("${spring.cloud.polaris.discovery.health-check-url:}") private String healthCheckUrl; + /** + * Millis interval of refresh of service info list. Default: 60000. + */ + private Long serviceListRefreshInterval = 60000L; + @Autowired private Environment environment; @@ -218,6 +223,14 @@ public class PolarisDiscoveryProperties { this.healthCheckUrl = healthCheckUrl; } + public Long getServiceListRefreshInterval() { + return serviceListRefreshInterval; + } + + public void setServiceListRefreshInterval(Long serviceListRefreshInterval) { + this.serviceListRefreshInterval = serviceListRefreshInterval; + } + @Override public String toString() { return "PolarisProperties{" + "token='" + token + '\'' + ", namespace='" diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java index 951c99f76..86e829080 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisDiscoveryHandler.java @@ -33,6 +33,7 @@ import com.tencent.polaris.api.rpc.GetInstancesRequest; import com.tencent.polaris.api.rpc.GetServicesRequest; import com.tencent.polaris.api.rpc.InstancesResponse; import com.tencent.polaris.api.rpc.ServicesResponse; +import com.tencent.polaris.client.api.SDKContext; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -52,6 +53,9 @@ public class PolarisDiscoveryHandler { @Autowired private ProviderAPI providerAPI; + @Autowired + private SDKContext sdkContext; + @Autowired private ConsumerAPI polarisConsumer; @@ -114,6 +118,10 @@ public class PolarisDiscoveryHandler { return providerAPI; } + public SDKContext getSdkContext() { + return sdkContext; + } + /** * Return all service for given namespace. * @return service list diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceChangeListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceChangeListener.java new file mode 100644 index 000000000..d52628f28 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceChangeListener.java @@ -0,0 +1,62 @@ +package com.tencent.cloud.polaris.registry; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import com.google.common.collect.Sets; +import com.tencent.polaris.api.plugin.registry.AbstractResourceEventListener; +import com.tencent.polaris.api.pojo.RegistryCacheValue; +import com.tencent.polaris.api.pojo.ServiceEventKey; +import com.tencent.polaris.client.pojo.ServicesByProto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.client.discovery.event.HeartbeatEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; + +/** + * Change listener of Polaris service info. + * + * @author Haotian Zhang + */ +public class PolarisServiceChangeListener extends AbstractResourceEventListener implements ApplicationEventPublisherAware { + + private static final Logger LOG = LoggerFactory.getLogger(PolarisServiceChangeListener.class); + + private static final AtomicInteger INDEX = new AtomicInteger(0); + + private ApplicationEventPublisher publisher; + + @Override + public void onResourceUpdated(ServiceEventKey svcEventKey, RegistryCacheValue oldValue, + RegistryCacheValue newValue) { + if (newValue.getEventType() != ServiceEventKey.EventType.SERVICE) { + return; + } + if (oldValue instanceof ServicesByProto && newValue instanceof ServicesByProto) { + LOG.debug("receive service={} change event", svcEventKey); + Set oldServiceInfoSet = ((ServicesByProto) oldValue).getServices().stream() + .map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet()); + Set newServiceInfoSet = ((ServicesByProto) newValue).getServices().stream() + .map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet()); + + Sets.SetView addServiceInfoSetView = Sets.difference(newServiceInfoSet, oldServiceInfoSet); + Sets.SetView deleteServiceInfoSetView = Sets.difference(oldServiceInfoSet, newServiceInfoSet); + + if (addServiceInfoSetView.isEmpty() && deleteServiceInfoSetView.isEmpty()) { + return; + } + LOG.info("Service info is update. Add service of {}. Delete service of {}", addServiceInfoSetView, deleteServiceInfoSetView); + + // Trigger reload of gateway route cache. + this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement())); + } + } + + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { + this.publisher = applicationEventPublisher; + } +} diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java index 83f8967f0..987413ed0 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java @@ -65,9 +65,11 @@ public class PolarisServiceRegistry implements ServiceRegistry { private final ScheduledExecutorService heartbeatExecutor; + private final PolarisServiceChangeListener polarisServiceChangeListener; + public PolarisServiceRegistry(PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryHandler polarisDiscoveryHandler, - MetadataLocalProperties metadataLocalProperties) { + MetadataLocalProperties metadataLocalProperties, PolarisServiceChangeListener polarisServiceChangeListener) { this.polarisDiscoveryProperties = polarisDiscoveryProperties; this.polarisDiscoveryHandler = polarisDiscoveryHandler; this.metadataLocalProperties = metadataLocalProperties; @@ -79,6 +81,8 @@ public class PolarisServiceRegistry implements ServiceRegistry { else { this.heartbeatExecutor = null; } + + this.polarisServiceChangeListener = polarisServiceChangeListener; } @Override @@ -116,6 +120,10 @@ public class PolarisServiceRegistry implements ServiceRegistry { // Start the heartbeat thread after the registration is successful. heartbeat(heartbeatRequest); } + + // Register service change listener + polarisDiscoveryHandler.getSdkContext().getExtensions().getLocalRegistry() + .registerResourceListener(polarisServiceChangeListener); } catch (Exception e) { log.error("polaris registry, {} register failed...{},", diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java index 93e282c8c..fba7be0bd 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java @@ -27,6 +27,7 @@ import com.tencent.polaris.client.api.SDKContext; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration; @@ -52,11 +53,10 @@ public class PolarisServiceRegistryAutoConfiguration { @Bean public PolarisServiceRegistry polarisServiceRegistry( - PolarisDiscoveryProperties polarisDiscoveryProperties, - PolarisDiscoveryHandler polarisDiscoveryHandler, - MetadataLocalProperties metadataLocalProperties) { + PolarisDiscoveryProperties polarisDiscoveryProperties, PolarisDiscoveryHandler polarisDiscoveryHandler, + MetadataLocalProperties metadataLocalProperties, PolarisServiceChangeListener polarisServiceChangeListener) { return new PolarisServiceRegistry(polarisDiscoveryProperties, - polarisDiscoveryHandler, metadataLocalProperties); + polarisDiscoveryHandler, metadataLocalProperties, polarisServiceChangeListener); } @Bean @@ -78,4 +78,9 @@ public class PolarisServiceRegistryAutoConfiguration { autoServiceRegistrationProperties, registration); } + @Bean + @ConditionalOnMissingBean + public PolarisServiceChangeListener polarisServiceChangeListener() { + return new PolarisServiceChangeListener(); + } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json index eb160ae93..7743b5f6c 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -59,6 +59,12 @@ "type": "java.lang.Integer", "defaultValue": 100, "description": "the weight of polaris instance , use to load-balance." + }, + { + "name": "spring.cloud.polaris.discovery.service-list-refresh-interval", + "type": "java.lang.Long", + "defaultValue": 60000, + "description": "Millis interval of refresh of service info list. Default: 60000." } ] } diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index 8e32288d0..1dc4849f3 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -70,7 +70,7 @@ - 1.4.1-Hoxton.SR9 + 1.4.2-Hoxton.SR9-SNAPSHOT 1.5.1 2.0.0 diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml index b820b2ee6..8acb66cb9 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml @@ -15,19 +15,52 @@ spring: address: grpc://127.0.0.1:8091 namespace: default enabled: true + discovery: + service-list-refresh-interval: 1000 gateway: discovery: locator: enabled: true - lowerCaseServiceId: false - routes: - - id: GatewayCalleeService - uri: lb://GatewayCalleeService - predicates: - - Path=/GatewayCalleeService/** - filters: - - StripPrefix=1 + 'predicates[0]': + name: Path + args: + patterns: '''/'' + serviceId + ''/**''' + 'filters[0]': + name: RewritePath + args: + regexp: '''/'' + serviceId + ''/(?.*)''' + replacement: '''/$\{remaining}''' + 'filters[1]': + name: Retry + args: + retries: 3 + exceptions: + '[0]': '''java.net.ConnectException''' + '[1]': '''java.io.IOException''' + statuses: + '[0]': '''BAD_GATEWAY''' + '[1]': '''SERVICE_UNAVAILABLE''' + series: + '[0]': '''CLIENT_ERROR''' + methods: + '[0]': '''GET''' + '[1]': '''POST''' + '[2]': '''PUT''' + '[3]': '''DELETE''' + backoff: + firstBackoff: '''100ms''' + maxBackoff: '''500ms''' + factor: 2 + basedOnPreviousValue: false +# routes: +# - id: GatewayCalleeService +# uri: lb://GatewayCalleeService +# predicates: +# - Path=/GatewayCalleeService/** +# filters: +# - StripPrefix=1 logging: level: org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml index 68f366fb0..ace6b329d 100644 --- a/src/checkstyle/checkstyle-suppressions.xml +++ b/src/checkstyle/checkstyle-suppressions.xml @@ -5,4 +5,5 @@ + \ No newline at end of file