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`||地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
|是否集成LoadBalancer|`spring.cloud.loadbalancer.nacos.enabled`|`false`|
|是否开启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
|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 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);
}
/**
* 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;
import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@ -35,19 +36,19 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
* @author yuhuangbin
* @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 ThreadPoolTaskScheduler taskScheduler;
private final AtomicLong nacosWatchIndex = new AtomicLong(0);
private final AtomicLong nacosHeartBeatIndex = new AtomicLong(0);
private final AtomicBoolean running = new AtomicBoolean(false);
private ApplicationEventPublisher publisher;
private ScheduledFuture<?> watchFuture;
private ScheduledFuture<?> heartBeatFuture;
public GatewayLocatorHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {
public NacosDiscoveryHeartBeatPublisher(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.taskScheduler = getTaskScheduler();
}
@ -61,19 +62,22 @@ public class GatewayLocatorHeartBeatPublisher implements ApplicationEventPublish
@Override
public void start() {
log.info("Start nacos gateway locator heartBeat task scheduler.");
this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
this::publishHeartBeat, this.nacosDiscoveryProperties.getWatchDelay());
if (this.running.compareAndSet(false, true)) {
log.info("Start nacos heartBeat task scheduler.");
this.heartBeatFuture = this.taskScheduler.scheduleWithFixedDelay(
this::publishHeartBeat, Duration.ofMillis(this.nacosDiscoveryProperties.getWatchDelay()));
}
}
@Override
public void stop() {
if (this.watchFuture != null) {
// shutdown current user-thread,
// then the other daemon-threads will terminate automatic.
this.taskScheduler.shutdown();
this.watchFuture.cancel(true);
if (this.running.compareAndSet(true, false)) {
if (this.heartBeatFuture != null) {
// shutdown current user-thread,
// then the other daemon-threads will terminate automatic.
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.
*/
public void publishHeartBeat() {
HeartbeatEvent event = new HeartbeatEvent(this, nacosWatchIndex.getAndIncrement());
HeartbeatEvent event = new HeartbeatEvent(this, nacosHeartBeatIndex.getAndIncrement());
this.publisher.publishEvent(event);
}
}

@ -47,6 +47,12 @@
"defaultValue": "false",
"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",
"type": "java.lang.String",

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

@ -76,20 +76,4 @@ public class NacosDiscoveryClientConfigurationTest {
.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