• spring-cloud-alibaba-dubbo-issues1805修复


    spring-cloud-alibaba-dubbo-issues1805修复

    这个issue就是我这前写了那两篇文章的那个issue

    Dubbo重启服务提供者或先启动服务消费者后启动服务提供者,消费者有时候会出现找不到服务的问题及解决

    https://mp.weixin.qq.com/s/L-ejXtV9wk-hPYAc2e3jvQ
    
    • 1

    Duboo项目集成升级问题解决

    https://mp.weixin.qq.com/s/-9t0tqnVX-A2fz4SNiPFdA
    
    • 1

    1.官方信息

    Spring Cloud Dubbo组件去留问题讨论 #2398

    https://github.com/alibaba/spring-cloud-alibaba/issues/2398
    
    • 1

    官方issue1805

    https://github.com/alibaba/spring-cloud-alibaba/issues/1805
    
    • 1

    官方issue1805提交

    https://github.com/alibaba/spring-cloud-alibaba/commit/fd8a6a6f6c262cbf8d20c049c84cd445651bd969
    
    • 1

    2.版本代码对比

    图片

    Spring-Cloud-Start-dubbo-2.2.6-RELEASE的服务注册自动配置类如下:

    图片

    /*
     * 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.autoconfigure;
    
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import com.alibaba.cloud.dubbo.autoconfigure.condition.MissingSpringCloudRegistryConfigPropertyCondition;
    import com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapStartCommandLineRunner;
    import com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapWrapper;
    import com.alibaba.cloud.dubbo.bootstrap.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;
    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;
    
    import org.springframework.aop.support.AopUtils;
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.beans.factory.SmartInitializingSingleton;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.AutoConfigureOrder;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    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.discovery.ConsulDiscoveryProperties;
    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;
    import org.springframework.context.SmartLifecycle;
    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.EventListener;
    import org.springframework.util.StringUtils;
    
    import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME;
    import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.ADDRESS;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.PROTOCOL;
    import static org.springframework.util.ObjectUtils.isEmpty;
    
    /**
     * Dubbo Service Registration Auto-{@link Configuration}.
     *
     * @author Mercy
     * @author theonefx
     */
    @Configuration(proxyBeanMethods = false)
    @Import({ DubboServiceRegistrationEventPublishingAspect.class,
    		DubboBootstrapStartCommandLineRunner.class })
    @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
    		matchIfMissing = true)
    @AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME,
    		CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME,
    		"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" },
    		value = { DubboMetadataAutoConfiguration.class })
    public class DubboServiceRegistrationAutoConfiguration {
    
    	/**
    	 * EurekaClientAutoConfiguration.
    	 */
    	public static final String EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration";
    
    	/**
    	 * ConsulAutoServiceRegistrationAutoConfiguration.
    	 */
    	public static final String CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration";
    
    	/**
    	 * ConsulAutoRegistration.
    	 */
    	public static final String CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration";
    
    	/**
    	 * ZookeeperAutoServiceRegistrationAutoConfiguration.
    	 */
    	public static final String ZOOKEEPER_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistrationAutoConfiguration";
    
    	private static final Logger logger = LoggerFactory
    			.getLogger(DubboServiceRegistrationAutoConfiguration.class);
    
    	@Autowired
    	private DubboServiceMetadataRepository dubboServiceMetadataRepository;
    
    	@Bean
    	@Conditional({ MissingSpringCloudRegistryConfigPropertyCondition.class })
    	public RegistryConfig defaultSpringCloudRegistryConfig() {
    		return new RegistryConfig(ADDRESS, PROTOCOL);
    	}
    
    	private Map<ServiceRegistry<Registration>, Set<Registration>> registrations = new ConcurrentHashMap<>();
    
    	@EventListener(DubboBootstrapStartedEvent.class)
    	public void onDubboBootstrapStarted(DubboBootstrapStartedEvent event) {
    		if (!event.getSource().isReady()) {
    			return;
    		}
    		registrations.forEach(
    				(registry, registrations) -> registrations.forEach(registration -> {
    					attachDubboMetadataServiceMetadata(registration);
    					registry.register(registration);
    				}));
    	}
    
    	@EventListener(ServiceInstancePreRegisteredEvent.class)
    	public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
    		Registration registration = event.getSource();
    		if (!DubboBootstrap.getInstance().isReady()
    				|| !DubboBootstrap.getInstance().isStarted()) {
    			ServiceRegistry<Registration> registry = event.getRegistry();
    			synchronized (registry) {
    				registrations.putIfAbsent(registry, new HashSet<>());
    				registrations.get(registry).add(registration);
    			}
    		}
    		else {
    			attachDubboMetadataServiceMetadata(registration);
    		}
    
    	}
    
    	@EventListener(ServiceInstancePreDeregisteredEvent.class)
    	public void onServiceInstancePreDeregistered(
    			ServiceInstancePreDeregisteredEvent event) {
    		ServiceRegistry<Registration> registry = event.getRegistry();
    		registrations.remove(registry);
    	}
    
    	private void attachDubboMetadataServiceMetadata(Registration registration) {
    		if (registration == null) {
    			return;
    		}
    		synchronized (registration) {
    			Map<String, String> metadata = registration.getMetadata();
    			attachDubboMetadataServiceMetadata(metadata);
    		}
    	}
    
    	private void attachDubboMetadataServiceMetadata(Map<String, String> metadata) {
    		Map<String, String> serviceMetadata = dubboServiceMetadataRepository
    				.getDubboMetadataServiceMetadata();
    		if (!isEmpty(serviceMetadata)) {
    			metadata.putAll(serviceMetadata);
    		}
    	}
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnBean(name = EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME)
    	class EurekaConfiguration implements SmartInitializingSingleton {
    
    		@Autowired
    		private ObjectProvider<Collection<ServiceBean>> serviceBeans;
    
    		@EventListener(DubboBootstrapStartedEvent.class)
    		public void onDubboBootstrapStarted(DubboBootstrapStartedEvent event) {
    			DubboBootstrapWrapper wrapper = event.getSource();
    			if (!wrapper.isReady()) {
    				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();
    
    				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);
    			}
    		}
    
    		/**
    		 * {@link EurekaServiceRegistry} will register current {@link ServiceInstance
    		 * service instance} on {@link EurekaAutoServiceRegistration#start()} execution(in
    		 * {@link SmartLifecycle#start() start phase}), thus this method must
    		 * {@link ServiceBean#export() export} all {@link ServiceBean ServiceBeans} in
    		 * advance.
    		 */
    		@Override
    		public void afterSingletonsInstantiated() {
    			Collection<ServiceBean> serviceBeans = this.serviceBeans.getIfAvailable();
    			if (!isEmpty(serviceBeans)) {
    				serviceBeans.forEach(ServiceBean::export);
    			}
    		}
    
    	}
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnBean(name = CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME)
    	@AutoConfigureOrder
    	class ConsulConfiguration {
    
    		@Autowired
    		private ConsulDiscoveryProperties consulDiscoveryProperties;
    
    		@EventListener(DubboBootstrapStartedEvent.class)
    		public void attachURLsIntoMetadataBeforeReRegist(
    				DubboBootstrapStartedEvent event) {
    			if (!event.getSource().isReady()) {
    				return;
    			}
    			registrations.entrySet().removeIf(entry -> {
    				Set<Registration> registrations = entry.getValue();
    				registrations.removeIf(registration -> {
    					Class<?> registrationClass = AopUtils.getTargetClass(registration);
    					String registrationClassName = registrationClass.getName();
    					return !CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME
    							.equalsIgnoreCase(registrationClassName);
    				});
    				return registrations.isEmpty();
    			});
    
    			registrations.forEach(
    					(registry, registrations) -> registrations.forEach(registration -> {
    						ConsulRegistration consulRegistration = (ConsulRegistration) registration;
    						attachURLsIntoMetadata(consulRegistration);
    					}));
    		}
    
    		@EventListener(ServiceInstancePreRegisteredEvent.class)
    		public void onServiceInstancePreRegistered(
    				ServiceInstancePreRegisteredEvent event) {
    			Registration registration = event.getSource();
    			attachURLsIntoMetadata((ConsulRegistration) registration);
    		}
    
    		private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) {
    			Map<String, String> serviceMetadata = dubboServiceMetadataRepository
    					.getDubboMetadataServiceMetadata();
    			if (isEmpty(serviceMetadata)) {
    				return;
    			}
    			NewService newService = consulRegistration.getService();
    			if (consulDiscoveryProperties.isTagsAsMetadata()) {
    				for (Map.Entry<String, String> entry : serviceMetadata.entrySet()) {
    					attAsTag(newService.getTags(), entry.getKey(), entry.getValue());
    				}
    			}
    			else {
    				newService.getMeta().putAll(serviceMetadata);
    			}
    		}
    
    		private void attAsTag(List<String> tags, String key, String value) {
    			Iterator<String> iter = tags.iterator();
    			while (iter.hasNext()) {
    				String tag = iter.next();
    				String[] tmp = tag.split("=");
    				if (StringUtils.pathEquals(tmp[0], key)) {
    					iter.remove();
    				}
    			}
    			tags.add(key + "=" + value);
    		}
    
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332

    DubboServiceRegistrationEventPublishingAspect类:

    /*
     * 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.registry;
    
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent;
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstanceRegisteredEvent;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    import org.springframework.cloud.client.serviceregistry.Registration;
    import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.ApplicationEventPublisherAware;
    
    /**
     * Dubbo Service Registration Event-Publishing Aspect.
     *
     * @author Mercy
     * @see ServiceInstancePreRegisteredEvent
     * @see ServiceInstanceRegisteredEvent
     * @see ServiceInstancePreDeregisteredEvent
     */
    @Aspect
    public class DubboServiceRegistrationEventPublishingAspect
    		implements ApplicationEventPublisherAware {
    
    	/**
    	 * The pointcut expression for {@link ServiceRegistry#register(Registration)}.
    	 */
    	public static final String REGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && target(registry) && args(registration)";
    
    	/**
    	 * The pointcut expression for {@link ServiceRegistry#deregister(Registration)}.
    	 */
    	public static final String DEREGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.deregister(*)) && target(registry) && args(registration)";
    
    	private ApplicationEventPublisher applicationEventPublisher;
    
    	@Before(value = REGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration")
    	public void beforeRegister(ServiceRegistry registry, Registration registration) {
    		applicationEventPublisher.publishEvent(
    				new ServiceInstancePreRegisteredEvent(registry, registration));
    	}
    
    	@Before(value = DEREGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration")
    	public void beforeDeregister(ServiceRegistry registry, Registration registration) {
    		applicationEventPublisher.publishEvent(
    				new ServiceInstancePreDeregisteredEvent(registry, registration));
    	}
    
    	@After(value = REGISTER_POINTCUT_EXPRESSION, argNames = "registry, registration")
    	public void afterRegister(ServiceRegistry registry, Registration registration) {
    		applicationEventPublisher
    				.publishEvent(new ServiceInstanceRegisteredEvent(registration));
    	}
    
    	@Override
    	public void setApplicationEventPublisher(
    			ApplicationEventPublisher applicationEventPublisher) {
    		this.applicationEventPublisher = applicationEventPublisher;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    spring-cloud-alibaba-2022.0.0.0

    https://github.com/alibaba/spring-cloud-alibaba/tree/fd8a6a6f6c262cbf8d20c049c84cd445651bd969
    
    • 1

    Spring-Cloud-Start-dubbo-2.2.7-RELEASE的服务注册自动配置类如下:

    ApplicationContextEvent是一个抽象类:在容器启动、刷新、关闭和停止的时候都会发送这个事件。

    图片

    /*
     * 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.autoconfigure;
    
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import com.alibaba.cloud.dubbo.autoconfigure.condition.MissingSpringCloudRegistryConfigPropertyCondition;
    import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
    import com.alibaba.cloud.dubbo.registry.DubboServiceRegistrationEventPublishingAspect;
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent;
    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.spring.ServiceBean;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import org.springframework.aop.support.AopUtils;
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.beans.factory.SmartInitializingSingleton;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.AutoConfigureOrder;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    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.serviceregistry.EurekaAutoServiceRegistration;
    import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
    import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
    import org.springframework.context.SmartLifecycle;
    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;
    import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.ADDRESS;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.PROTOCOL;
    import static org.springframework.util.ObjectUtils.isEmpty;
    
    /**
     * Dubbo Service Registration Auto-{@link Configuration}.
     *
     * @author Mercy
     */
    @Configuration(proxyBeanMethods = false)
    @Import({ DubboServiceRegistrationEventPublishingAspect.class })
    @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
    		matchIfMissing = true)
    @AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME,
    		CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME,
    		"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" },
    		value = { DubboMetadataAutoConfiguration.class })
    public class DubboServiceRegistrationAutoConfiguration {
    
    	/**
    	 * EurekaClientAutoConfiguration.
    	 */
    	public static final String EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration";
    
    	/**
    	 * ConsulAutoServiceRegistrationAutoConfiguration.
    	 */
    	public static final String CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration";
    
    	/**
    	 * ConsulAutoRegistration.
    	 */
    	public static final String CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration";
    
    	/**
    	 * ZookeeperAutoServiceRegistrationAutoConfiguration.
    	 */
    	public static final String ZOOKEEPER_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistrationAutoConfiguration";
    
    	private static final Logger logger = LoggerFactory
    			.getLogger(DubboServiceRegistrationAutoConfiguration.class);
    
    	@Autowired
    	private DubboServiceMetadataRepository dubboServiceMetadataRepository;
    
    	@Bean
    	@Conditional({ MissingSpringCloudRegistryConfigPropertyCondition.class })
    	public RegistryConfig defaultSpringCloudRegistryConfig() {
    		return new RegistryConfig(ADDRESS, PROTOCOL);
    	}
    
    	private Map<ServiceRegistry<Registration>, Set<Registration>> registrations = new ConcurrentHashMap<>();
    
        // 监听ApplicationContextEvent这个事件重新注册dubbo的服务
    	@Order
    	@EventListener(ApplicationContextEvent.class)
    	public void attachDubboMetadataAndRegistAgain(ApplicationContextEvent event) {
    		registrations.forEach(
    				(registry, registrations) -> registrations.forEach(registration -> {
    					attachDubboMetadataServiceMetadata(registration);
    					registry.register(registration);
    				}));
    	}
       //dubbo的aspect切拦截nacos服务注册前会发送这个事件,监听到该事件后需要将注册到nacos的服务加入到registrations
    	@EventListener(ServiceInstancePreRegisteredEvent.class)
    	public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
    		Registration registration = event.getSource();
    		ServiceRegistry<Registration> registry = event.getRegistry();
            // 这里加了一个jvm的锁
    		synchronized (registry) {
    			registrations.putIfAbsent(registry, new HashSet<>());
    			registrations.get(registry).add(registration);
    		}
    	}
        
        //dubbo的aspect切面拦截服务取消注册前会发送这个时间,监听到该事件后需要将服务注册信息从registrations中移除
    	@EventListener(ServiceInstancePreDeregisteredEvent.class)
    	public void onServiceInstancePreDeregistered(
    			ServiceInstancePreDeregisteredEvent event) {
    		ServiceRegistry<Registration> registry = event.getRegistry();
    		registrations.remove(registry);
    	}
    
    	private void attachDubboMetadataServiceMetadata(Registration registration) {
    		if (registration == null) {
    			return;
    		}
    		synchronized (registration) {
    			Map<String, String> metadata = registration.getMetadata();
    			attachDubboMetadataServiceMetadata(metadata);
    		}
    	}
        //这里是dubbo服务元数据,会加入到一个map集合中,然后会走服务变更,通知服务订阅者重新拉取最新的注册的服务信息(猜测)。
    	private void attachDubboMetadataServiceMetadata(Map<String, String> metadata) {
    		Map<String, String> serviceMetadata = dubboServiceMetadataRepository
    				.getDubboMetadataServiceMetadata();
    		if (!isEmpty(serviceMetadata)) {
    			metadata.putAll(serviceMetadata);
    		}
    	}
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnBean(name = EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME)
    	class EurekaConfiguration implements SmartInitializingSingleton {
    
    		@Autowired
    		private ObjectProvider<Collection<ServiceBean>> serviceBeans;
    
    		@Order(Ordered.LOWEST_PRECEDENCE - 1)
    		@EventListener(ApplicationContextEvent.class)
    		public void onServiceInstancePreRegistered(ApplicationContextEvent event) {
    			registrations.forEach((registry, registrations)-> registrations.forEach(registration -> {
    				EurekaRegistration eurekaRegistration = (EurekaRegistration) registration;
    				InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager().getInfo();
    				attachDubboMetadataServiceMetadata(instanceInfo.getMetadata());
    			}));
    		}
    
    		/**
    		 * {@link EurekaServiceRegistry} will register current {@link ServiceInstance
    		 * service instance} on {@link EurekaAutoServiceRegistration#start()} execution(in
    		 * {@link SmartLifecycle#start() start phase}), thus this method must
    		 * {@link ServiceBean#export() export} all {@link ServiceBean ServiceBeans} in
    		 * advance.
    		 */
    		@Override
    		public void afterSingletonsInstantiated() {
    			Collection<ServiceBean> serviceBeans = this.serviceBeans.getIfAvailable();
    			if (!isEmpty(serviceBeans)) {
    				serviceBeans.forEach(ServiceBean::export);
    			}
    		}
    
    	}
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnBean(name = CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME)
    	@AutoConfigureOrder
    	class ConsulConfiguration {
    
    		@Order(Ordered.LOWEST_PRECEDENCE - 1)
    		@EventListener(ApplicationContextEvent.class)
    		public void attachURLsIntoMetadataBeforeReRegist(ApplicationContextEvent event) {
    			registrations.entrySet().removeIf(entry -> {
    				Set<Registration> registrations = entry.getValue();
    				registrations.removeIf(registration -> {
    					Class<?> registrationClass = AopUtils.getTargetClass(registration);
    					String registrationClassName = registrationClass.getName();
    					return !CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME
    							.equalsIgnoreCase(registrationClassName);
    				});
    				return registrations.isEmpty();
    			});
    
    			registrations.forEach(
    					(registry, registrations) -> registrations.forEach(registration -> {
    						ConsulRegistration consulRegistration = (ConsulRegistration) registration;
    						attachURLsIntoMetadata(consulRegistration);
    					}));
    		}
    
    		private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) {
    			NewService newService = consulRegistration.getService();
    			Map<String, String> serviceMetadata = dubboServiceMetadataRepository
    					.getDubboMetadataServiceMetadata();
    			if (!isEmpty(serviceMetadata)) {
    				List<String> tags = newService.getTags();
    				for (Map.Entry<String, String> entry : serviceMetadata.entrySet()) {
    					tags.add(entry.getKey() + "=" + entry.getValue());
    				}
    			}
    		}
    
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240

    说明:

    图片

    将2022.0.0.0的start的服务注册自动装配类扣出来,放到项目中,然后注释EurekaConfiguration和ConsulConfiguration的自动装配即可,如果要用可以把先关的包引入进来,这个版本的start和2.2.7版本的这个start相差不大,可以替换使用

    图片

    之前通过升级解决这个问题,估计是巧合吧Duboo项目集成升级问题解决,百思不得其解,然后我就去git的官网上看了下找到了这个issue,然后官方是在spring-cloud-alibaba-2022.0.0.0这个版本才修复有提交代码记录的,由于这个版本所需要的版本如下:

    图片

    我们项目中的springBoot的版本是2.3.12.RELEASE,所以都不想升级版本依赖,所以想了这个办法,直接将这个类抠出来用下就可以了。

    3.修改尝试

    图片

    package com.alibaba.cloud.dubbo.autoconfigure;
    
    /*
     * 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.
     */
    
    import com.alibaba.cloud.dubbo.autoconfigure.condition.MissingSpringCloudRegistryConfigPropertyCondition;
    import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
    import com.alibaba.cloud.dubbo.registry.DubboServiceRegistrationEventPublishingAspect;
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreDeregisteredEvent;
    import com.alibaba.cloud.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
    import org.apache.dubbo.config.RegistryConfig;
    import org.apache.dubbo.config.spring.ServiceBean;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.serviceregistry.Registration;
    import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
    import org.springframework.context.SmartLifecycle;
    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.annotation.Order;
    
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME;
    import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.ADDRESS;
    import static com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory.PROTOCOL;
    import static org.springframework.util.ObjectUtils.isEmpty;
    
    /**
     * Dubbo Service Registration Auto-{@link Configuration}.
     *
     * @author Mercy
     */
    @Configuration(proxyBeanMethods = false)
    @Import({DubboServiceRegistrationEventPublishingAspect.class})
    @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
    @AutoConfigureAfter(name = {EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME, CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME, "org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration"}, value = {DubboMetadataAutoConfiguration.class})
    public class DubboServiceRegistrationAutoConfiguration {
    
        /**
         * EurekaClientAutoConfiguration.
         */
        public static final String EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration";
    
        /**
         * ConsulAutoServiceRegistrationAutoConfiguration.
         */
        public static final String CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration";
    
        /**
         * ConsulAutoRegistration.
         */
        public static final String CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration";
    
        /**
         * ZookeeperAutoServiceRegistrationAutoConfiguration.
         */
        public static final String ZOOKEEPER_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.zookeeper.serviceregistry.ZookeeperAutoServiceRegistrationAutoConfiguration";
    
        private static final Logger logger = LoggerFactory.getLogger(DubboServiceRegistrationAutoConfiguration.class);
    
        @Autowired
        private DubboServiceMetadataRepository dubboServiceMetadataRepository;
    
        @Bean
        @Conditional({MissingSpringCloudRegistryConfigPropertyCondition.class})
        public RegistryConfig defaultSpringCloudRegistryConfig() {
            return new RegistryConfig(ADDRESS, PROTOCOL);
        }
    
        private Map<ServiceRegistry<Registration>, Set<Registration>> registrations = new ConcurrentHashMap<>();
    
        @Order
        @EventListener(ApplicationContextEvent.class)
        public void attachDubboMetadataAndRegistAgain(ApplicationContextEvent event) {
            registrations.forEach((registry, registrations) -> registrations.forEach(registration -> {
                attachDubboMetadataServiceMetadata(registration);
                registry.register(registration);
            }));
        }
    
        @EventListener(ServiceInstancePreRegisteredEvent.class)
        public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
            Registration registration = event.getSource();
            ServiceRegistry<Registration> registry = event.getRegistry();
            synchronized (registry) {
                registrations.putIfAbsent(registry, new HashSet<>());
                registrations.get(registry).add(registration);
            }
        }
    
        @EventListener(ServiceInstancePreDeregisteredEvent.class)
        public void onServiceInstancePreDeregistered(ServiceInstancePreDeregisteredEvent event) {
            ServiceRegistry<Registration> registry = event.getRegistry();
            registrations.remove(registry);
        }
    
        private void attachDubboMetadataServiceMetadata(Registration registration) {
            if (registration == null) {
                return;
            }
            synchronized (registration) {
                Map<String, String> metadata = registration.getMetadata();
                attachDubboMetadataServiceMetadata(metadata);
            }
        }
    
        private void attachDubboMetadataServiceMetadata(Map<String, String> metadata) {
            Map<String, String> serviceMetadata = dubboServiceMetadataRepository.getDubboMetadataServiceMetadata();
            if (!isEmpty(serviceMetadata)) {
                metadata.putAll(serviceMetadata);
            }
        }
    
        /*@Configuration(proxyBeanMethods = false)
        @ConditionalOnBean(name = EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME)
        class EurekaConfiguration implements SmartInitializingSingleton {
    
            @Autowired
            private ObjectProvider> serviceBeans;
    
            @Order(Ordered.LOWEST_PRECEDENCE - 1)
            @EventListener(ApplicationContextEvent.class)
            public void onServiceInstancePreRegistered(ApplicationContextEvent event) {
                registrations.forEach((registry, registrations) -> registrations.forEach(registration -> {
                    EurekaRegistration eurekaRegistration = (EurekaRegistration) registration;
                    InstanceInfo instanceInfo = eurekaRegistration.getApplicationInfoManager().getInfo();
                    attachDubboMetadataServiceMetadata(instanceInfo.getMetadata());
                }));
            }
    
            *//**
         * {@link EurekaServiceRegistry} will register current {@link ServiceInstance
         * service instance} on {@link EurekaAutoServiceRegistration#start()} execution(in
         * {@link SmartLifecycle#start() start phase}), thus this method must
         * {@link ServiceBean#export() export} all {@link ServiceBean ServiceBeans} in
         * advance.
         *//*
            @Override
            public void afterSingletonsInstantiated() {
                Collection<ServiceBean> serviceBeans = this.serviceBeans.getIfAvailable();
                if (!isEmpty(serviceBeans)) {
                    serviceBeans.forEach(ServiceBean::export);
                }
            }
    
        }*/
    
        /*@Configuration(proxyBeanMethods = false)
        @ConditionalOnBean(name = CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME)
        @AutoConfigureOrder
        class ConsulConfiguration {
    
            @Order(Ordered.LOWEST_PRECEDENCE - 1)
            @EventListener(ApplicationContextEvent.class)
            public void attachURLsIntoMetadataBeforeReRegist(ApplicationContextEvent event) {
                registrations.entrySet().removeIf(entry -> {
                    Set registrations = entry.getValue();
                    registrations.removeIf(registration -> {
                        Class registrationClass = AopUtils.getTargetClass(registration);
                        String registrationClassName = registrationClass.getName();
                        return !CONSUL_AUTO_SERVICE_AUTO_REGISTRATION_CLASS_NAME
                                .equalsIgnoreCase(registrationClassName);
                    });
                    return registrations.isEmpty();
                });
    
                registrations.forEach(
                        (registry, registrations) -> registrations.forEach(registration -> {
                            ConsulRegistration consulRegistration = (ConsulRegistration) registration;
                            attachURLsIntoMetadata(consulRegistration);
                        }));
            }
    
            private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) {
                NewService newService = consulRegistration.getService();
                Map serviceMetadata = dubboServiceMetadataRepository
                        .getDubboMetadataServiceMetadata();
                if (!isEmpty(serviceMetadata)) {
                    List tags = newService.getTags();
                    for (Map.Entry entry : serviceMetadata.entrySet()) {
                        tags.add(entry.getKey() + "=" + entry.getValue());
                    }
                }
            }
    
        }*/
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214

    之前那两篇文章大致的思路上大致方向是对的,Spring-Cloud-Start-dubbo-2.2.6-RELEASE和Spring-Cloud-Start-dubbo-2.2.7-RELEASE的springBoot的基本流程是一样的,nacos的注册是在在servlet容器启动后进行,dubbo的BootStrap.start()触发是在容器刷新后触发,由于2.3.x的springBoot的版本的容器刷新事件是在nacos的servlet容器启动之后(之前的思路是将dubbo.start()触发提前到nacos注册服务之前,这种是行不通的,因为Spring-Cloud-Start-dubbo的服务注册的start的流程上就有问题,提前这个顺序只会搞出更多的问题),所以就有有dubbo服务还没有注册完,所以就没有触发更新和通知操作

    spring-context-5.2.15.RELEASE

    @Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				registerBeanPostProcessors(beanFactory);
    
    				// Initialize message source for this context.
    				initMessageSource();
    
    				// Initialize event multicaster for this context.
    				initApplicationEventMulticaster();
    
    				// Initialize other special beans in specific context subclasses.
                    //这里是servelet容器启动后会触发通知nacos注册
    				onRefresh();
    
    				// Check for listener beans and register them.
    				registerListeners();
    
    				// Instantiate all remaining (non-lazy-init) singletons.
    				finishBeanFactoryInitialization(beanFactory);
    
    				// Last step: publish corresponding event.
                    //这里是触发dubbo启动;
    				finishRefresh();
    			}
    
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
    
    				// Destroy already created singletons to avoid dangling resources.
    				destroyBeans();
    
    				// Reset 'active' flag.
    				cancelRefresh(ex);
    
    				// Propagate exception to caller.
    				throw ex;
    			}
    
    			finally {
    				// Reset common introspection caches in Spring's core, since we
    				// might not ever need metadata for singleton beans anymore...
    				resetCommonCaches();
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    finishRefresh();

    protected void finishRefresh() {
    		// Clear context-level resource caches (such as ASM metadata from scanning).
    		clearResourceCaches();
    
    		// Initialize lifecycle processor for this context.
    		initLifecycleProcessor();
    
    		// Propagate refresh to lifecycle processor first.
    		getLifecycleProcessor().onRefresh();
            // 容器刷新时间,触发dubbStrap.start();
    		// Publish the final event.
    		publishEvent(new ContextRefreshedEvent(this));
    
    		// Participate in LiveBeansView MBean, if active.
    		LiveBeansView.registerApplicationContext(this);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    start中的服务元数据注册管理:

    private void attachDubboMetadataServiceMetadata(Map<String, String> metadata) {
            Map<String, String> serviceMetadata = dubboServiceMetadataRepository.getDubboMetadataServiceMetadata();
            if (!isEmpty(serviceMetadata)) {
                metadata.putAll(serviceMetadata);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    getDubboMetadataServiceMetadata方法

    public Map<String, String> getDubboMetadataServiceMetadata() {
    
    		List<URL> dubboMetadataServiceURLs = dubboMetadataServiceExporter.export();
    
    		// remove the exported URLs of DubboMetadataService
    		removeDubboMetadataServiceURLs(dubboMetadataServiceURLs);
    
    		Map<String, String> metadata = newHashMap();
    
    		addDubboMetadataServiceURLsMetadata(metadata, dubboMetadataServiceURLs);
    		addDubboProtocolsPortMetadata(metadata);
    		addRevision(metadata);
    
    		return Collections.unmodifiableMap(metadata);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    addDubboProtocolsPortMetadata方法

    private void addDubboProtocolsPortMetadata(Map metadata) {
    
    		allExportedURLs.values().stream().flatMap(v -> v.stream()).forEach(url -> {
    			String protocol = url.getProtocol();
    			String propertyName = getDubboProtocolPropertyName(protocol);
    			String propertyValue = valueOf(url.getPort());
    			metadata.put(propertyName, propertyValue);
    		});
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通过去源码里面找allExportedURLs的逻辑,大致猜测可以知道,当服务注册、变更(刷新)或失败等会有一些触发服务变更通知订阅者的逻辑,这样在只要是服务有变动都可以感知到,然后nacos通知到订阅者,你订阅的服务有变动了,你需要拉取下最新的服务然后更新下本地的服务列表,这个就是我大致的逻辑猜测。

    private final MultiValueMap<String, URL> allExportedURLs = new LinkedMultiValueMap<>();
    
    • 1

    4.验证

    在公司测试环境依赖使用的是之前升级后的依赖,然后使用上面那个start部署测试环境后,服务提供者部署重启,服务消费者不用重启,然后访问应用,服务消费者可以正常的访问到服务提供者的服务。

    5.总结

    希望我的分享对你有帮助,有兴趣的可以去看下dubbo的相关源码和具体的逻辑是怎样的,上面的是我的一些猜测(合理的猜想 + 验证),感觉是这么一个感觉,请一键三连,么么么哒!

  • 相关阅读:
    2023年,千万别裸辞....
    GraphQL
    模拟浏览器与服务器交互(简易TomCat框架)
    Word目录中自动添加自定义样式的多级标题的方法
    jar包或exe程序设置为windows服务
    Sidecar-详解 JuiceFS CSI Driver 新模式
    STM32——端口复用与重映射概述与配置(HAL库)
    X-Formers
    零编程制作疫情全国行政区地图,理性看待各地疫情防控减码
    【服务器数据恢复】HP StorageWorks系列服务器RAID5两块盘离线的数据恢复
  • 原文地址:https://blog.csdn.net/qq_34905631/article/details/133317363