fix: Nacos integration with SpringBootAdmin.(2022.x) (#3318)

pull/3253/merge
ZhangBin 2 years ago committed by GitHub
parent ccbdfe60d1
commit 53d466fc4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -355,5 +355,6 @@ spring.cloud.nacos.discovery.ip-type=IPv6
|接入点|`spring.cloud.nacos.discovery.endpoint`||地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 |接入点|`spring.cloud.nacos.discovery.endpoint`||地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
|是否集成LoadBalancer|`spring.cloud.loadbalancer.nacos.enabled`|`false`| |是否集成LoadBalancer|`spring.cloud.loadbalancer.nacos.enabled`|`false`|
|是否开启Nacos Watch|`spring.cloud.nacos.discovery.watch.enabled`|`false`|可以设置成 true 来开启 watch |是否开启Nacos Watch|`spring.cloud.nacos.discovery.watch.enabled`|`false`|可以设置成 true 来开启 watch
|是否开启Nacos Discovery HeartBeat|`spring.cloud.nacos.discovery.heart-beat.enabled`|`false`|可以设置成 true 来开启 heart beat
|=== |===

@ -359,5 +359,5 @@ The following shows the other configurations of the starter of Nacos Discovery:
|Endpoint|`spring.cloud.nacos.discovery.endpoint`||The domain name of a certain service in a specific region. You can retrieve the server address dynamically with this domain name |Endpoint|`spring.cloud.nacos.discovery.endpoint`||The domain name of a certain service in a specific region. You can retrieve the server address dynamically with this domain name
|Integrate LoadBalancer or not|`spring.cloud.loadbalancer.nacos.enabled`|`false`| |Integrate LoadBalancer or not|`spring.cloud.loadbalancer.nacos.enabled`|`false`|
|Enable Nacos Watch|`spring.cloud.nacos.discovery.watch.enabled`|`false`|set to true to enable watch |Enable Nacos Watch|`spring.cloud.nacos.discovery.watch.enabled`|`false`|set to true to enable watch
|Enable Nacos Discovery HeartBeat|`spring.cloud.nacos.discovery.heart-beat.enabled`|`false`|set to true to enable heart beat
|=== |===

@ -64,16 +64,4 @@ public class NacosDiscoveryClientConfiguration {
return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties); return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);
} }
/**
* Spring Cloud Gateway HeartBeat .
* publish an event every 30 seconds
* see https://github.com/alibaba/spring-cloud-alibaba/issues/2868
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.gateway.discovery.locator.enabled", matchIfMissing = false)
public GatewayLocatorHeartBeatPublisher gatewayLocatorHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {
return new GatewayLocatorHeartBeatPublisher(nacosDiscoveryProperties);
}
} }

@ -0,0 +1,85 @@
/*
* Copyright 2013-2023 the original author or authors.
*
* 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
*
* https://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.alibaba.cloud.nacos.discovery;
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaojing
* @author echooymxq
* @author ruansheng
* @author zhangbin
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureAfter(value = NacosDiscoveryAutoConfiguration.class,
name = "de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration")
public class NacosDiscoveryHeartBeatConfiguration {
/**
* Nacos HeartBeat is no longer enabled by default .
* publish an event every 30 seconds
* see https://github.com/alibaba/spring-cloud-alibaba/issues/2868
* see https://github.com/alibaba/spring-cloud-alibaba/issues/3258
*/
@Bean
@ConditionalOnMissingBean
@Conditional(NacosDiscoveryHeartBeatCondition.class)
public NacosDiscoveryHeartBeatPublisher nacosDiscoveryHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosDiscoveryHeartBeatPublisher(nacosDiscoveryProperties);
}
private static class NacosDiscoveryHeartBeatCondition extends AnyNestedCondition {
NacosDiscoveryHeartBeatCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
/**
* Spring Cloud Gateway HeartBeat .
*/
@ConditionalOnProperty(value = "spring.cloud.gateway.discovery.locator.enabled", matchIfMissing = false)
static class GatewayLocatorHeartBeatEnabled { }
/**
* Spring Boot Admin HeartBeat .
*/
@ConditionalOnBean(type = "de.codecentric.boot.admin.server.cloud.discovery.InstanceDiscoveryListener")
static class SpringBootAdminHeartBeatEnabled { }
/**
* Nacos HeartBeat .
*/
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.heart-beat.enabled", matchIfMissing = false)
static class NacosDiscoveryHeartBeatEnabled { }
}
}

@ -16,6 +16,7 @@
package com.alibaba.cloud.nacos.discovery; package com.alibaba.cloud.nacos.discovery;
import java.time.Duration;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -35,19 +36,19 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
* @author yuhuangbin * @author yuhuangbin
* @author ruansheng * @author ruansheng
*/ */
public class GatewayLocatorHeartBeatPublisher implements ApplicationEventPublisherAware, SmartLifecycle { public class NacosDiscoveryHeartBeatPublisher implements ApplicationEventPublisherAware, SmartLifecycle {
private static final Logger log = LoggerFactory.getLogger(GatewayLocatorHeartBeatPublisher.class); private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryHeartBeatPublisher.class);
private final NacosDiscoveryProperties nacosDiscoveryProperties; private final NacosDiscoveryProperties nacosDiscoveryProperties;
private final ThreadPoolTaskScheduler taskScheduler; private final ThreadPoolTaskScheduler taskScheduler;
private final AtomicLong nacosWatchIndex = new AtomicLong(0); private final AtomicLong nacosHeartBeatIndex = new AtomicLong(0);
private final AtomicBoolean running = new AtomicBoolean(false); private final AtomicBoolean running = new AtomicBoolean(false);
private ApplicationEventPublisher publisher; private ApplicationEventPublisher publisher;
private ScheduledFuture<?> watchFuture; private ScheduledFuture<?> heartBeatFuture;
public GatewayLocatorHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) { public NacosDiscoveryHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties; this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.taskScheduler = getTaskScheduler(); this.taskScheduler = getTaskScheduler();
} }
@ -61,19 +62,22 @@ public class GatewayLocatorHeartBeatPublisher implements ApplicationEventPublish
@Override @Override
public void start() { public void start() {
log.info("Start nacos gateway locator heartBeat task scheduler."); if (this.running.compareAndSet(false, true)) {
this.watchFuture = this.taskScheduler.scheduleWithFixedDelay( log.info("Start nacos heartBeat task scheduler.");
this::publishHeartBeat, this.nacosDiscoveryProperties.getWatchDelay()); this.heartBeatFuture = this.taskScheduler.scheduleWithFixedDelay(
this::publishHeartBeat, Duration.ofMillis(this.nacosDiscoveryProperties.getWatchDelay()));
}
} }
@Override @Override
public void stop() { public void stop() {
if (this.watchFuture != null) { if (this.running.compareAndSet(true, false)) {
// shutdown current user-thread, if (this.heartBeatFuture != null) {
// then the other daemon-threads will terminate automatic. // shutdown current user-thread,
this.taskScheduler.shutdown(); // then the other daemon-threads will terminate automatic.
this.watchFuture.cancel(true); this.taskScheduler.shutdown();
this.heartBeatFuture.cancel(true);
}
} }
} }
@ -96,7 +100,7 @@ public class GatewayLocatorHeartBeatPublisher implements ApplicationEventPublish
* nacos doesn't support watch now , publish an event every 30 seconds. * nacos doesn't support watch now , publish an event every 30 seconds.
*/ */
public void publishHeartBeat() { public void publishHeartBeat() {
HeartbeatEvent event = new HeartbeatEvent(this, nacosWatchIndex.getAndIncrement()); HeartbeatEvent event = new HeartbeatEvent(this, nacosHeartBeatIndex.getAndIncrement());
this.publisher.publishEvent(event); this.publisher.publishEvent(event);
} }
} }

@ -47,6 +47,12 @@
"defaultValue": "false", "defaultValue": "false",
"description": "enable nacos discovery watch or not ." "description": "enable nacos discovery watch or not ."
}, },
{
"name": "spring.cloud.nacos.discovery.heart-beat.enabled",
"type": "java.lang.Boolean",
"defaultValue": "false",
"description": "enable nacos discovery heart beat or not ."
},
{ {
"name": "spring.cloud.nacos.discovery.username", "name": "spring.cloud.nacos.discovery.username",
"type": "java.lang.String", "type": "java.lang.String",

@ -2,6 +2,7 @@ com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryHeartBeatConfiguration
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration

@ -76,20 +76,4 @@ public class NacosDiscoveryClientConfigurationTest {
.run(context -> assertThat(context).hasSingleBean(NacosWatch.class)); .run(context -> assertThat(context).hasSingleBean(NacosWatch.class));
} }
@Test
public void testDefaultGatewayLocatorHeartBeatPublisher() {
contextRunner.run(context ->
assertThat(context).doesNotHaveBean(GatewayLocatorHeartBeatPublisher.class)
);
}
@Test
public void testGatewayLocatorHeartBeatPublisherEnabled() {
contextRunner
.withPropertyValues("spring.cloud.gateway.discovery.locator.enabled=true")
.run(context ->
assertThat(context).hasSingleBean(GatewayLocatorHeartBeatPublisher.class)
);
}
} }

@ -0,0 +1,72 @@
/*
* Copyright 2013-2023 the original author or authors.
*
* 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
*
* https://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.alibaba.cloud.nacos.discovery;
import com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;
import com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;
import com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author <a href="mailto:zhangbin1010@qq.com">zhangbin</a>
**/
public class NacosDiscoveryHeartBeatConfigurationTest {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
AutoServiceRegistrationConfiguration.class,
NacosServiceRegistryAutoConfiguration.class,
UtilAutoConfiguration.class,
UtilIPv6AutoConfiguration.class,
NacosServiceAutoConfiguration.class,
NacosDiscoveryAutoConfiguration.class,
NacosDiscoveryClientConfiguration.class,
NacosDiscoveryHeartBeatConfiguration.class, this.getClass()));
@Test
public void testDefaultNacosDiscoveryHeartBeatPublisher() {
contextRunner.run(context ->
assertThat(context).doesNotHaveBean(NacosDiscoveryHeartBeatPublisher.class)
);
}
@Test
public void testNacosDiscoveryHeartBeatPublisherEnabledForGateway() {
contextRunner
.withPropertyValues("spring.cloud.gateway.discovery.locator.enabled=true")
.run(context ->
assertThat(context).hasSingleBean(NacosDiscoveryHeartBeatPublisher.class)
);
}
@Test
public void testNacosDiscoveryHeartBeatPublisherEnabledForProperties() {
contextRunner
.withPropertyValues("spring.cloud.nacos.discovery.heart-beat.enabled=true")
.run(context ->
assertThat(context).hasSingleBean(NacosDiscoveryHeartBeatPublisher.class)
);
}
}
Loading…
Cancel
Save