spring-cloud-alibaba-dubbo-issues1805修复

spring-cloud-alibaba-dubbo-issues1805修复

文章目录

    • @[toc]
  • 1.官方信息
  • 2.版本代码对比
  • 3.修改尝试
  • 4.验证
  • 5.总结

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

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

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

Duboo项目集成升级问题解决

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

1.官方信息

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

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

官方issue1805

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

官方issue1805提交

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

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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>* @author <a href="mailto:chenxilzx1@gmail.com">theonefx</a>*/
@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);@Autowiredprivate 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 {@Autowiredprivate 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.*/@Overridepublic 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)@AutoConfigureOrderclass ConsulConfiguration {@Autowiredprivate 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);}}}

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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>* @see ServiceInstancePreRegisteredEvent* @see ServiceInstanceRegisteredEvent* @see ServiceInstancePreDeregisteredEvent*/
@Aspect
public class DubboServiceRegistrationEventPublishingAspectimplements 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));}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}}

spring-cloud-alibaba-2022.0.0.0

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

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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>*/
@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);@Autowiredprivate 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 {@Autowiredprivate 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.*/@Overridepublic 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)@AutoConfigureOrderclass 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());}}}}}

说明:

图片

将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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>*/
@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);@Autowiredprivate 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 {@Autowiredprivate 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.*//*@Overridepublic 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)@AutoConfigureOrderclass 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());}}}}*/}

之前那两篇文章大致的思路上大致方向是对的,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

@Overridepublic 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();}}}

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);}

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

private void attachDubboMetadataServiceMetadata(Map<String, String> metadata) {Map<String, String> serviceMetadata = dubboServiceMetadataRepository.getDubboMetadataServiceMetadata();if (!isEmpty(serviceMetadata)) {metadata.putAll(serviceMetadata);}}

getDubboMetadataServiceMetadata方法

public Map<String, String> getDubboMetadataServiceMetadata() {List<URL> dubboMetadataServiceURLs = dubboMetadataServiceExporter.export();// remove the exported URLs of DubboMetadataServiceremoveDubboMetadataServiceURLs(dubboMetadataServiceURLs);Map<String, String> metadata = newHashMap();addDubboMetadataServiceURLsMetadata(metadata, dubboMetadataServiceURLs);addDubboProtocolsPortMetadata(metadata);addRevision(metadata);return Collections.unmodifiableMap(metadata);}

addDubboProtocolsPortMetadata方法

private void addDubboProtocolsPortMetadata(Map<String, String> 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);});}

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

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

4.验证

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

5.总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148427.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java泛型理解

什么是泛型&#xff1f; 我们都知道 Java 中有形参和实参之分&#xff0c;是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数&#xff0c;其本身没有确定的值。在调用函数时&#xff0c;实参将赋值给形参。 而泛型是一种参数化的类型&#xff08…

以太网基础学习(四)——IP协议

一 、IP协议概述 IP&#xff08;Internet Protocol&#xff0c;互联网协议&#xff09;是互联网通信的基础协议&#xff0c;它负责将数据包从源地址传输到目的地址。IP协议定义了如何封装数据包&#xff0c;如何寻址数据包以及如何路由数据包&#xff0c;它是随着互联网的出现而…

Pytorch基础:Tensor的reshape方法

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html?spm1001.2014.3001.5482 在Pytorch中&#xff0c;reshape是Tensor的一个重要方法&#xff0c;它与Numpy中的reshape类似&#xff0c;用于返回一个改变了形状但数据和数据顺序和原来一致的…

linux入门---信号的理解

目录标题 如何理解计算机中的信号如何查看计算机中的信号初步了解信号的保存和发送如何向目标进程发送信号情景一&#xff1a;使用键盘发送信号情景二&#xff1a;系统调用发送信号情景三&#xff1a;硬件异常产生信号情景四&#xff1a;软件条件产生信号 核心转储信号的两个问…

单调栈---基础数据结构与算法

简介 栈 (stack) 又名堆栈&#xff0c;是一种数据结构&#xff0c;向一个栈插入新元素又称作进栈、入栈或压栈&#xff0c;从一个栈删除元素又称作出栈或退栈。 栈是一种只允许在表尾进行插入和删除操作的线性表&#xff0c;也就是我们所说的后进先出&#xff0c;我们把栈想象…

【Linux】ping命令详解

目录 一、ping概述 二、Ping用法 三、ping参数详解 四、使用 五、Wireshark抓取ICMP请求应答消息 一、ping概述 ping 命令用于测试与目标主机之间的连接。它向目标主机发送一个ICMP&#xff08;Internet Control Message Protocol&#xff09;Internet控制报文协议回显请求…

知识图谱小白入门(1):neo4j的安装与CQL的使用

文章目录 序一、安装neo4j1.1 下载neo4j1.2 安装JDK1.3 BUG&#xff1a;dbms failed to start 二、CQL语法2.1 CQL语法创建节点查询节点创建关系查询关系2.2 习题 习题答案 序 知识图谱&#xff0c;是一种实体间的信息与关系知识的网状结构&#xff0c;借用图论中点与边的概念…

SLAM从入门到精通(用python实现机器人运动控制)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在ROS下面&#xff0c;开发的方法很多&#xff0c;可以是c&#xff0c;可以是python。大部分接口操作类的应用&#xff0c;其实都可以用python来开…

「专题速递」数字人直播带货、传统行业数字化升级、远程协作中的低延时视频、地产物业中的通讯终端...

音视频技术作为企业数字化转型的核心要素之一&#xff0c;已在各行各业展现出广泛的应用和卓越的价值。实时通信、社交互动、高清视频等技术不仅令传统行业焕发新生&#xff0c;还为其在生产、管理、服务提供与维护等各个领域带来了巨大的助力&#xff0c;实现了生产效率和服务…

postgresql-聚合函数增强功能

postgresql-聚合函数增强功能 按季度统计入职员工 按季度统计入职员工 select -- extract截取&#xff0c;按季度进行统计入职员工总数 extract(year from hire_date), count(*) filter(where extract(quarter from hire_date) 1) "第一季度", count(*) filter(wh…

httpserver 下载服务器demo 以及libevent版本的 httpserver

实现效果如下&#xff1a; 图片可以直接显示 cpp h 这些可以直接显示 其他的 则是提示是否要下载 单线程 还有bug 代码如下 先放上来 #include "httpserver.h" #include "stdio.h" #include <stdlib.h> #include <arpa/inet.h> #include…

录屏软件——Vizard

Vizard&#xff0c;美且实用的网页端录屏软件&#xff0c;轻巧不占内存。Windows/Mac OS均适用。 可以录电脑操作、录软件教程、录网课、录bug、录工作汇报、录创作素材&#xff08;游戏&#xff09;……几乎能想到的一切录屏场景。 除了完全免费的在线录屏&#xff0c;Vizar…

激光雷达中实现F-P标准具高热稳定性的帕尔贴精密温控解决方案

摘要&#xff1a;法布里-珀罗标准具作为一种具有高温度敏感性的精密干涉分光器件&#xff0c;在具体应用中对热稳定性具有很高的要求&#xff0c;如温度波动不能超过0.01℃&#xff0c;为此本文提出了相应的高精度恒温控制解决方案。解决方案具体针对温度控制精度和温度均匀性控…

c++中的动态内存管理

目录 1.内存分布 2.c语言动态内存管理 3.c动态内存管理 4.operator new 与operator delete 函数 5.定位new 6.malloc/free 与 new/delete 的区别 1.内存分布 首先我们需要了解一下数据在内存中的分布&#xff0c;请看以下代码&#xff1a; int globalVar 1; static in…

C#停车场管理系统

目录 一、绪论1.1内容简介及意义1.2开发工具及技术介绍 二、总体设计2.1系统总体架构2.2登录模块总体设计2.3主界面模块总体设计2.4停车证管理模块总体设计2.5停车位管理模块总体设计2.6员工管理模块总体设计2.7其他模块总体设计 三、详细设计3.1登录模块设计3.2主界面模块设计…

想要精通算法和SQL的成长之路 - 并查集的运用和案例(省份数量)

想要精通算法和SQL的成长之路 - 并查集的运用 前言一. 并查集的使用和模板1.1 初始化1.2 find 查找函数1.3 union 合并集合1.4 connected 判断相连性1.5 完整代码 二. 运用案例 - 省份数量 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 并查集的使用和模板 先说一下并查集…

力扣:119. 杨辉三角 II(Python3)

题目&#xff1a; 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09…

计算机竞赛 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

JavaScript:从入门到进阶的旅程

JavaScript是一种广泛使用的编程语言&#xff0c;为网页和应用程序提供了交互性和动态性。从初学者到资深开发者&#xff0c;JavaScript都是一项值得掌握的技能。在本文中&#xff0c;我们将探讨JavaScript的基础知识&#xff0c;以及一些进阶的概念和技巧。 一、JavaScript简…

Spring的注解开发-注解原理解析-xml方式/注解方式组件扫描

目录 Spring注解的解析原理 xml配置组件扫描 注解方式配置组件扫描 原理图 yysy&#xff0c;没有搞太明白&#xff0c;真的复杂&#xff0c;欢迎大佬留言解惑 Spring注解的解析原理 使用Component等注解配置完毕后&#xff0c;要配置组件扫描才能使注解生效 xml配置组件扫…