文章摘要(AI生成)
本文介绍了Spring Cloud服务的注册和发现流程,首先通过spring-cloud-commons包定义了注册和发现的规范流程,然后通过各个注册中心和管理中心进行具体的服务注册和实现。服务注册和发现包括两个步骤,一是通过EnableDiscoveryClient注解开启自动注册服务,二是在容器启动时向注册中心的注册表进行注册。其中,HostInfoEnvironmentPostProcessor获取了服务实例所属主机信息的属性,并将其封装到springCloudClientHostInfo属性源中。CompatibilityNotMetFailureAnalyzer用于解析当配置不兼容报错时,返回适当的提示信息。在Spring的自动配置中,引入了客户端状态配置和四种客户端的配置,包括通用客户端、响应式客户端、复合客户端和简单客户端。
spring-cloud服务进行服务注册发现是首先通过spring-cloud-commons包定义了一套注册和发现的规范流程,然后再有各个注册中心和管理中心进行具体的服务注册和实现。服务发现注册一共有两件事情,一个就是通过EnableDiscoveryClient
注解开启服务自动注册,第二就是在容器启动时就向注册中心的注册表进行注册。
spring-cloud-commons配置说明
其spring.factories文件如下:
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.configuration.CompatibilityNotMetFailureAnalyzer
HostInfoEnvironmentPostProcessor
获取了服务实例所属主机信息的属性,并将其封装到springCloudClientHostInfo
属性源中。
CompatibilityNotMetFailureAnalyzer
用于解析当配置不兼容报错时,返回适当的提示信息。
其spring文件夹下,自动配置引入的配置bean有:
##客户端状态配置:通用客户端、响应式客户端
org.springframework.cloud.client.CommonsClientAutoConfiguration
org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration
##四种客户端:复合客户端、响应式复合客户端、简单客户端、简单响应式客户端
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration
org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration
##客户端共享资源配置
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration
##客户端复杂均衡配置
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration
##服务注册表配置
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration
##网络IO工具类
org.springframework.cloud.commons.util.UtilAutoConfiguration
##版本验证
org.springframework.cloud.configuration.CompatibilityVerifierAutoConfiguration
##服务的发现与注册
org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
##OAuth2访问支持
org.springframework.cloud.commons.security.ResourceServerTokenRelayAutoConfiguration
##配置属性解析绑定
org.springframework.cloud.commons.config.CommonsConfigAutoConfiguration
是否开启服务发现
EnableDiscoveryClient
注解
其在注解中导入了EnableDiscoveryClientImportSelector
来完成服务注册与发现的过程
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* 如果为 true,ServiceRegistry 将自动注册本地服务器。
* @return - {@code true} 如果想开启自动注册则返回true.
*/
boolean autoRegister() default true;
}
导入服务发现配置-EnableDiscoveryClientImportSelector
实现了SpringFactoryImportSelector
,它的作用是读取spring.factories
文件,并根据EnableDiscoveryClient
注解中autoRegister属性值,如果属性值为true,则向其中添加org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration
属性;如果属性值为false,则向环境变量中添加spring.cloud.service-registry.auto-registration.enabled
属性,值为false,并且添加springCloudDiscoveryClient
属性源。
问:
SpringFactoryImportSelector
是什么作用?答:
SpringFactoryImportSelector
是Spring框架中的一个类,它的作用是通过读取spring.factories
文件中的配置信息,选择并导入需要加载的Spring配置类。在Spring Boot中,
SpringFactoryImportSelector
通常用于自动装配(Auto-configuration)的机制。当使用某个Spring Boot Starter时,该Starter会在其META-INF/spring.factories
文件中定义自己的自动配置类。SpringFactoryImportSelector
会根据这些配置信息,选择并导入需要加载的自动配置类。具体来说,
SpringFactoryImportSelector
的作用如下:
- 读取
spring.factories
文件:SpringFactoryImportSelector
会在类路径下查找并读取spring.factories
文件,该文件中记录了各个Spring组件的配置信息。- 选择需要导入的配置类:根据
spring.factories
文件中的配置信息,SpringFactoryImportSelector
会根据一定的规则选择需要导入的配置类,通常是自动配置类。- 导入配置类:根据选择的配置类,
SpringFactoryImportSelector
会将它们以ImportSelector
的形式(也可以是其他适配器形式)导入到Spring容器中。通过这种机制,Spring Boot能够根据应用程序的依赖关系和配置文件的设定,自动加载相应的自动配置类,从而实现自动装配和快速配置应用程序的功能。
总而言之,
SpringFactoryImportSelector
是Spring框架中用于读取spring.factories
文件,并根据配置信息选择和导入需要加载的Spring配置类的类。
源码注释:
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
//获取EnableDiscoveryClient注解中的autoRegister属性
boolean autoRegister = attributes.getBoolean("autoRegister");
//如果autoRegister属性开启,则导入AutoServiceRegistrationConfiguration
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = importsList.toArray(new String[0]);
}
//如果autoRegister属性关闭,则将spring.cloud.service-registry.auto-registration设置为false
//并创建springCloudDiscoveryClient属性集合,添加到spring容器配置集合中
else {
Environment env = getEnvironment();
if (env instanceof ConfigurableEnvironment configEnv) {
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
MapPropertySource propertySource = new MapPropertySource("springCloudDiscoveryClient", map);
configEnv.getPropertySources().addLast(propertySource);
}
}
return imports;
}
}
服务发现自动配置-AutoServiceRegistrationAutoConfiguration
实现了InitializingBean
,即在容器启动时就注册该配置类。该配置类声明了两个类,一个适用于服务注册操作的AutoServiceRegistration
,一个是包含服务注册属性的AutoServiceRegistrationProperties
。
源码注释:
@Configuration(proxyBeanMethods = false)
@Import(AutoServiceRegistrationConfiguration.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationAutoConfiguration implements InitializingBean {
//服务注册
@Autowired(required = false)
private AutoServiceRegistration autoServiceRegistration;
//服务注册配置
@Autowired
private AutoServiceRegistrationProperties properties;
//如果服务注册的属性为空且为快速失败则抛异常中断服务启动
@Override
public void afterPropertiesSet() {
if (this.autoServiceRegistration == null && this.properties.isFailFast()) {
throw new IllegalStateException(
"Auto Service Registration has " + "been requested, but there is no AutoServiceRegistration bean");
}
}
}
服务注册属性配置AutoServiceRegistrationProperties
本身是一个配置属性类,其包含了服务发现注册的几个开关:
- 是否自动注册,默认是true
- 是否向管理服务注册,默认是true
- 没有配置服务注册时,是否可以启动失败,默认是false
分别对应以下三个配置属性:
###是否自动注册
spring.cloud.service-registry.auto-registration.enabled=true
###是否向管理服务注册
spring.cloud.service-registry.auto-registration.register-management=true
###没有配置服务注册时,是否可以启动失败
spring.cloud.service-registry.auto-registration.fail-fast=true
服务发现具体实现AutoServiceRegistration
:
在服务发现包中,由AutoServiceRegistration
的定义的子类AbstractAutoServiceRegistration
进行了默认实现,从它的定义中:
public abstract class AbstractAutoServiceRegistration<R extends Registration>
implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent>
我们可以发现,其实现了ApplicationContextAware
和ApplicationListener
,那么他又实现了容器获取和监听容器事件的操作。
spring容器获取:
//获取spring容器和spring容器的环境
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.environment = this.context.getEnvironment();
}
监听容器事件,完成服务注册:
//监听消息
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
ApplicationContext context = event.getApplicationContext();
if (context instanceof ConfigurableWebServerApplicationContext) {
if ("management".equals(((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
return;
}
}
this.port.compareAndSet(0, event.getWebServer().getPort());
this.start();
}
public void start() {
//判断服务发现是否开启
if (!isEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Discovery Lifecycle disabled. Not starting");
}
return;
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
// 线程安全判断:仅当 nonSecurePort 大于 0 且由于下面的 containerPortInitializer 而尚未运行时才初始化
if (!this.running.get()) {
//发布实例预注册事件-InstancePreRegisteredEvent
this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));
//执行注册表启动前的处理方法
registrationLifecycles.forEach(
registrationLifecycle -> registrationLifecycle.postProcessBeforeStartRegister(getRegistration()));
//向注册表注册。注册通常包含有关实例的信息,例如其主机名和端口。
register();
//执行注册表启动后的处理方法
this.registrationLifecycles.forEach(
registrationLifecycle -> registrationLifecycle.postProcessAfterStartRegister(getRegistration()));
//是否向管理服务注册
if (shouldRegisterManagement()) {
//执行管理注册表启动前的处理方法
this.registrationManagementLifecycles
.forEach(registrationManagementLifecycle -> registrationManagementLifecycle
.postProcessBeforeStartRegisterManagement(getManagementRegistration()));
//向管理服务注册
this.registerManagement();
//执行管理注册表启动后的处理方法
registrationManagementLifecycles
.forEach(registrationManagementLifecycle -> registrationManagementLifecycle
.postProcessAfterStartRegisterManagement(getManagementRegistration()));
}
//发布实例注册完成事件-InstanceRegisteredEvent
this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));
this.running.compareAndSet(false, true);
}
}
在监听到webserver初始化完成的事件时,我们会判断他是否是management应用。如果不是management应用(actuator或者admin应用不会注册到注册中心中,所以无法在注册中心看到这类应用),那么将更新服务的端口以及启动服务注册流程。
Q:ConfigurableWebServerApplicationContext的serverNameSpace为management时,该spring应用是哪一种web服务器部署的应用?
A:当
ConfigurableWebServerApplicationContext
的serverNamespace
属性值为management
时,这表示Spring应用是以管理服务器模式部署的应用(Management Server Deployment)。在Spring Boot中,可以通过
application.properties
或application.yaml
配置文件的server.namespace
属性来设置serverNamespace
。如果将该属性值设为management
,则Spring Boot应用将以管理服务器模式运行。管理服务器模式是指Spring Boot应用作为一个独立的管理服务器来运行,用于管理和监控其他独立的应用。通常,在微服务架构中,使用一个管理服务器来运行一些共享的管理和监控组件,例如Spring Boot Admin或Actuator。这些组件可以收集、监控和管理多个独立的应用的运行状况和性能指标。
在管理服务器模式下,Spring应用仅用于管理和监控其他应用,而不承担实际的业务逻辑。它可以提供一种集中管理和监控的解决方案,简化了对微服务体系中多个应用的管理和监控工作。
所以,当
ConfigurableWebServerApplicationContext
的serverNamespace
属性值为management
时,这表示Spring应用以管理服务器模式部署,用于管理和监控其他独立应用。
服务注册表-ServiceRegistry
通过注册表的方式,负责服务实例的注册和注销:
public interface ServiceRegistry<R extends Registration> {
/**
* 向注册表注册服务实例。注册通常包含有关实例的信息,例如其主机名和端口。
* @param registration 要注册的元数据
*/
void register(R registration);
/**
* 将注册表的服务实例注销。
* @param registration 要注册的元数据
*/
void deregister(R registration);
/**
* 关闭注册表
*/
void close();
/**
* 获取已注册服务的实例状态
*/
void setStatus(R registration, String status);
/**
* 获取已注册服务的实例状态
*/
<T> T getStatus(R registration);
}
服务实例信息-Registration
其继承了ServiceInstance
接口,包括了已注册的实例ID、服务ID、主机、端口、服务uri、实例关联的元数据和scheme信息。
小结
本文只是介绍了spring-cloud-commons如何定义了一套标准的服务注册和发现规范,下篇文章将介绍eureka的服务注册和发现(本文图片中出现的EurekaAutoServiceRegistration
)是怎么样的一个实现流程.
评论区