diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java index feea3582..82ad817c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java @@ -82,7 +82,7 @@ public final class NacosDataParserHandler { } NacosByteArrayResource nacosByteArrayResource = new NacosByteArrayResource( configValue.getBytes(), configName); - nacosByteArrayResource.setFilename(getFileName(configName , extension)); + nacosByteArrayResource.setFilename(getFileName(configName, extension)); List> propertySourceList = propertySourceLoader .load(configName, nacosByteArrayResource); if (CollectionUtils.isEmpty(propertySourceList)) { @@ -135,8 +135,8 @@ public final class NacosDataParserHandler { return DEFAULT_EXTENSION; } - private String getFileName(String name,String extension){ - if(StringUtils.isEmpty(extension)){ + private String getFileName(String name, String extension) { + if (StringUtils.isEmpty(extension)) { return name; } if (StringUtils.isEmpty(name)) { @@ -145,7 +145,7 @@ public final class NacosDataParserHandler { int idx = name.lastIndexOf(DOT); if (idx > 0 && idx < name.length() - 1) { String ext = name.substring(idx + 1); - if(extension.equalsIgnoreCase(ext)){ + if (extension.equalsIgnoreCase(ext)) { return name; } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index 97ab7310..9a79a568 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -40,11 +40,11 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; * @author eshun */ public class NacosServiceRegistry implements ServiceRegistry { - + private static final String STATUS_UP = "UP"; - + private static final String STATUS_DOWN = "DOWN"; - + private static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class); private final NacosDiscoveryProperties nacosDiscoveryProperties; @@ -123,7 +123,8 @@ public class NacosServiceRegistry implements ServiceRegistry { @Override public void setStatus(Registration registration, String status) { - if (!STATUS_UP.equalsIgnoreCase(status) && !STATUS_DOWN.equalsIgnoreCase(status)) { + if (!STATUS_UP.equalsIgnoreCase(status) + && !STATUS_DOWN.equalsIgnoreCase(status)) { log.warn("can't support status {},please choose UP or DOWN", status); return; } @@ -141,8 +142,8 @@ public class NacosServiceRegistry implements ServiceRegistry { try { Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties(); - nacosServiceManager.getNamingMaintainService(nacosProperties) - .updateInstance(serviceId, nacosDiscoveryProperties.getGroup(), instance); + nacosServiceManager.getNamingMaintainService(nacosProperties).updateInstance( + serviceId, nacosDiscoveryProperties.getGroup(), instance); } catch (Exception e) { throw new RuntimeException("update nacos instance status fail", e); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index c1d23cb1..5861fdf0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -24,6 +24,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import com.alibaba.cloud.dubbo.autoconfigure.condition.MissingSpringCloudRegistryConfigPropertyCondition; +import com.alibaba.cloud.dubbo.metadata.DubboBootstrapCommandLineRunner; +import com.alibaba.cloud.dubbo.metadata.event.DubboBootstrapStartedEvent; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; import com.alibaba.cloud.dubbo.registry.DubboServiceRegistrationEventPublishingAspect; import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent; @@ -31,6 +33,7 @@ import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreRegisteredEvent; import com.ecwid.consul.v1.agent.model.NewService; import com.netflix.appinfo.InstanceInfo; import org.apache.dubbo.config.RegistryConfig; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; import org.apache.dubbo.config.spring.ServiceBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,6 +50,7 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; +import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry; @@ -55,9 +59,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.event.ApplicationContextEvent; import org.springframework.context.event.EventListener; -import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME; @@ -72,7 +74,8 @@ import static org.springframework.util.ObjectUtils.isEmpty; * @author Mercy */ @Configuration(proxyBeanMethods = false) -@Import({ DubboServiceRegistrationEventPublishingAspect.class }) +@Import({ DubboServiceRegistrationEventPublishingAspect.class, + DubboBootstrapCommandLineRunner.class }) @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, @@ -116,8 +119,11 @@ public class DubboServiceRegistrationAutoConfiguration { private Map, Set> registrations = new ConcurrentHashMap<>(); @Order - @EventListener(ApplicationContextEvent.class) - public void attachDubboMetadataAndRegistAgain(ApplicationContextEvent event) { + @EventListener(DubboBootstrapStartedEvent.class) + public void attachDubboMetadataAndRegistAgain(DubboBootstrapStartedEvent event) { + if (!event.getSource().isReady() || !event.getSource().isStarted()) { + return; + } registrations.forEach( (registry, registrations) -> registrations.forEach(registration -> { attachDubboMetadataServiceMetadata(registration); @@ -128,11 +134,18 @@ public class DubboServiceRegistrationAutoConfiguration { @EventListener(ServiceInstancePreRegisteredEvent.class) public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { Registration registration = event.getSource(); - ServiceRegistry registry = event.getRegistry(); - synchronized (registry) { - registrations.putIfAbsent(registry, new HashSet<>()); - registrations.get(registry).add(registration); + if (!DubboBootstrap.getInstance().isReady() + || !DubboBootstrap.getInstance().isStarted()) { + ServiceRegistry registry = event.getRegistry(); + synchronized (registry) { + registrations.putIfAbsent(registry, new HashSet<>()); + registrations.get(registry).add(registration); + } } + else { + attachDubboMetadataServiceMetadata(registration); + } + } @EventListener(ServiceInstancePreDeregisteredEvent.class) @@ -167,14 +180,62 @@ public class DubboServiceRegistrationAutoConfiguration { @Autowired private ObjectProvider> serviceBeans; - @Order(Ordered.LOWEST_PRECEDENCE - 1) - @EventListener(ApplicationContextEvent.class) - public void onServiceInstancePreRegistered(ApplicationContextEvent event) { - registrations.forEach((registry, registrations)-> registrations.forEach(registration -> { + @EventListener(DubboBootstrapStartedEvent.class) + public void onServiceInstancePreRegistered(DubboBootstrapStartedEvent event) { + DubboBootstrap bootstrap = event.getSource(); + if (!bootstrap.isReady() || !bootstrap.isStarted()) { + return; + } + registrations.forEach( + (registry, registrations) -> registrations.removeIf(registration -> { + if (!(registration instanceof EurekaRegistration)) { + return false; + } + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + InstanceInfo instanceInfo = eurekaRegistration + .getApplicationInfoManager().getInfo(); + + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.UP); + + attachDubboMetadataServiceMetadata(instanceInfo.getMetadata()); + eurekaRegistration.getApplicationInfoManager() + .registerAppMetadata(instanceInfo.getMetadata()); + eurekaRegistration.getApplicationInfoManager() + .setInstanceStatus(InstanceInfo.InstanceStatus.UP); + return true; + })); + } + + @EventListener(ServiceInstancePreRegisteredEvent.class) + public void onServiceInstancePreRegistered( + ServiceInstancePreRegisteredEvent event) { + Registration registration = event.getSource(); + if (!(registration instanceof EurekaRegistration)) { + return; + } + + if (DubboBootstrap.getInstance().isReady() + && DubboBootstrap.getInstance().isStarted()) { EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; - InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager().getInfo(); + InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager() + .getInfo(); + + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.UP); + attachDubboMetadataServiceMetadata(instanceInfo.getMetadata()); - })); + eurekaRegistration.getApplicationInfoManager() + .registerAppMetadata(instanceInfo.getMetadata()); + } + else { + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + EurekaInstanceConfigBean config = (EurekaInstanceConfigBean) eurekaRegistration + .getInstanceConfig(); + config.setInitialStatus(InstanceInfo.InstanceStatus.STARTING); + } } /** @@ -199,9 +260,12 @@ public class DubboServiceRegistrationAutoConfiguration { @AutoConfigureOrder class ConsulConfiguration { - @Order(Ordered.LOWEST_PRECEDENCE - 1) - @EventListener(ApplicationContextEvent.class) - public void attachURLsIntoMetadataBeforeReRegist(ApplicationContextEvent event) { + @EventListener(DubboBootstrapStartedEvent.class) + public void attachURLsIntoMetadataBeforeReRegist( + DubboBootstrapStartedEvent event) { + if (!event.getSource().isReady() || !event.getSource().isStarted()) { + return; + } registrations.entrySet().removeIf(entry -> { Set registrations = entry.getValue(); registrations.removeIf(registration -> { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DubboBootstrapCommandLineRunner.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DubboBootstrapCommandLineRunner.java new file mode 100644 index 00000000..dc819d0e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DubboBootstrapCommandLineRunner.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2018 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.dubbo.metadata; + +import com.alibaba.cloud.dubbo.metadata.event.DubboBootstrapStartedEvent; +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.stereotype.Component; + +/** + * @see com.alibaba.cloud.dubbo.metadata.event.DubboBootstrapPreStartEvent + * @see com.alibaba.cloud.dubbo.metadata.event.DubboBootstrapStartedEvent + * @author theonefx + */ + +@Component +public class DubboBootstrapCommandLineRunner + implements CommandLineRunner, ApplicationEventPublisherAware { + + private ApplicationEventPublisher applicationEventPublisher; + + @Override + public void setApplicationEventPublisher( + ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + @Override + public void run(String... args) { + applicationEventPublisher.publishEvent( + new DubboBootstrapStartedEvent(DubboBootstrap.getInstance())); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapPreStartEvent.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapPreStartEvent.java new file mode 100644 index 00000000..b38f0c84 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapPreStartEvent.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2018 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.dubbo.metadata.event; + +import org.springframework.context.ApplicationEvent; + +/** + * @author theonefx + */ +public class DubboBootstrapPreStartEvent extends ApplicationEvent { + + /** + * Create a new {@code ApplicationEvent}. + * @param source the object on which the event initially occurred or with which the + * event is associated (never {@code null}) + */ + public DubboBootstrapPreStartEvent(Object source) { + super(source); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapStartedEvent.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapStartedEvent.java new file mode 100644 index 00000000..c41996b8 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/event/DubboBootstrapStartedEvent.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2018 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.dubbo.metadata.event; + +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.springframework.context.ApplicationEvent; + +/** + * @author theonefx + */ +public class DubboBootstrapStartedEvent extends ApplicationEvent { + + /** + * Create a new {@code ApplicationEvent}. + * @param source the object on which the event initially occurred or with which the + * event is associated (never {@code null}) + */ + public DubboBootstrapStartedEvent(Object source) { + super(source); + } + + @Override + public DubboBootstrap getSource() { + return (DubboBootstrap) super.getSource(); + } + +}