SpringCloud组件内部一定会有spring-cloud-commons 和 spring-cloud-context 这两个依赖中的一个。比如 spring-cloud-netflix-eureka-server, spring-cloud-netflix-eureka-client, spring-cloud-netflix-ribbon。它们内部的这两个依赖都是optional。这些组件对应的starter内部使用了 spring-cloud-starter 依赖,因为spring-cloud-starter依赖内部依赖了spring-cloud-context、spring-cloud-commons和spring-boot-starter(springboot全套架构)。
本文将分析spring-cloud-commons模块。关于spring-cloud-context将在下一篇文章中分析。
spring-cloud-commons模块是spring在分布式领域上(服务发现,服务注册,断路器,负载均衡)的规范定义(spring-cloud-netflix是具体的实现,也就是Netflix OSS里的各种组件实现了这个commons规范),可以被所有的Spring Cloud客户端使用(比如服务发现领域的eureka,consul)。下面将根据包名来分析一下内部的一些接口和类。
actuator功能
actuator子包里提供了一个id为 features 的 FeaturesEndpoint
。该Endpoint里会展示应用具体的feature。具体的内容在HasFeatures
集合属性中,HasFeatures
内部包含 List<Class<?>> abstractFeatures
和 List<NamedFeature> namedFeatures
这两个属性。
NamedFeature
里有 String name
和 Class<?> type
这两个属性。
abstractFeatures属性处理过程:遍历abstractFeatures集合,在ApplicationContext中找出具体Class的bean。然后根据这个具体的Class构造Feature(Feature拥有type,name,version和vendor属性)。
namedFeatures属性处理过程:遍历namedFeatures集合,直接根据NamedFeature李的name和type构造Feature。
比如CommonsClientAutoConfiguration
里就使用如下方式构造了一个HasFeatures。这个HasFeatures只有abstractFeatures属性有值,对应的Class是DiscoveryClient
和LoadBalancerClient
:
1 | HasFeatures.abstractFeatures(DiscoveryClient.class, LoadBalancerClient.class); |
下面就是一个FeaturesEndpoint
内容,对应DiscoveryClient
和LoadBalancerClient
接口,具体的type就是CompositeDiscoveryClient
和RibbonLoadBalancerClient
:
1 | { |
circuitbreaker功能
断路器功能。
circuitbreaker子包里面定义了一个注解@EnableCircuitBreaker
和一个Import Selector。只要使用了该注解就会import这个selector:
1 | (EnableCircuitBreakerImportSelector.class) |
selector也很简单,代码如下:
1 | 100) (Ordered.LOWEST_PRECEDENCE - |
继承了 SpringFactoryImportSelector
, 内部会使用工厂加载机制。去加载META-INF/spring.factories里key为 org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker
的类。该机制生效的前期是 spring.cloud.circuit.breaker.enabled
配置为true,默认值就是true。
circuitbreaker子包相当于了定义了断路器的加载机制。在spring.factories里配置对应的类和开关配置即可生效。具体的实现由其它模块提供。
discovery功能
服务发现功能。
定义了DiscoveryClient
接口和EnableDiscoveryClient
注解。
定义了一些各种服务发现组件客户端里的读取服务操作:
1 | public interface DiscoveryClient { |
@EnableDiscoveryClient
注解import了EnableDiscoveryClientImportSelector
这个selector。该注解内部有个属性 boolean autoRegister() default true;
表示是否自动注册,默认是true。
selector内部会找出 META-INF/spring.factories里key为org.springframework.cloud.client.discovery.EnableDiscoveryClient
的类。
如果自动注册属性为true,会在找出的这些类里再加上一个类:org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration
。 AutoServiceRegistrationConfiguration
内部会使用@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
触发构造AutoServiceRegistrationProperties
这个bean。像eureka,nacos,它们的自动化配置类里都使用了@ConditionalOnBean(AutoServiceRegistrationProperties.class)
来确保存在AutoServiceRegistrationProperties这个bean存在的时候才会构造AutoServiceRegistration
进行注册。
如果自动注册属性为false,在Environment里加一个PropertySource,内部的配置项是spring.cloud.service-registry.auto-registration.enabled
,值是false(代表不构造AutoServiceRegistrationProperties.class
)。这样eureka,nacos都不会注册
discovery子包内部还有其它一些功能:
simple
简单的服务发现实现类
SimpleDiscoveryClient
,具体的服务实例从SimpleDiscoveryProperties
配置中获取。SimpleDiscoveryProperties
配置 读取前缀为spring.cloud.discovery.client.simple
的配置。读取的结果放到Map里Map<String, List<SimpleServiceInstance>>
。这里SimpleServiceInstance
实现了ServiceInstance接口。 具体的属性值从SimpleDiscoveryProperties
中获取SimpleDiscoveryClientAutoConfiguration
自动化配置类在 spring.factories里key为org.springframework.boot.autoconfigure.EnableAutoConfiguration
的配置项中。内部会构造SimpleDiscoveryProperties
、SimpleDiscoveryClient
noop
什么都不做的服务发现实现类,已经被废弃,建议使用 simple 子模块里的类代替
health
SpringBoot的那套health机制与SpringCloud结合。使用DiscoveryClient获取服务实例的信息
event
定义了一些心跳检测事件,服务注册事件
composite
定义了
CompositeDiscoveryClient
。 看名字也知道,组合各个服务发现客户端的一个客户端。默认会根据CompositeDiscoveryClientAutoConfiguration
自动化配置类构造出CompositeDiscoveryClient
。默认清下我们注入的DiscoveryClient
就是这个CompositeDiscoveryClient
serviceregistry功能
服务注册功能。
定义了服务注册的接口 ServiceRegistry<R extends Registration>
,Registration
接口继承了服务实例ServiceInstance
接口,未新增新方法,留作以后扩展使用。
1 | public interface ServiceRegistry<R extends Registration> { |
定义了一些自动化配置类:
ServiceRegistryAutoConfiguration
内部会根据条件注解判断是否构造
ServiceRegistryEndpoint
,该endpoint会暴露ServiceRegistry
的状态信息,也可以设置ServiceRegistry
的状态信息AutoServiceRegistrationAutoConfiguration
在
@EnableDiscoveryClient
注解打开自注册开关的时候才会生效,内部import了AutoServiceRegistrationConfiguration
这个类,该类内部会使用@EnableConfigurationProperties
注解构造AutoServiceRegistrationProperties这个bean
定义了一个接口AutoServiceRegistration
和一个抽象类 AbstractAutoServiceRegistration
,用于处理服务自动注册逻辑。一般我们自定义的服务注册逻辑只需要继承该类即可。
AutoServiceRegistration
接口无任何方法声明,用于标记是否是服务自动注册。
AbstractAutoServiceRegistration
抽象类实现了AutoServiceRegistration
接口,定义了4个抽象方法:
1 | // 服务注册信息的配置数据 |
AbstractAutoServiceRegistration
抽象类内部逻辑总结:
- 构造方法里必须有个
ServiceRegistry
参数,服务注册相关的逻辑都使用该接口完成 - 监听
WebServerInitializedEvent
事件。当WebServer初始化完毕后(Spring ApplicationContext也已经refresh后),使用ServiceRegistry
注册服务,具体的服务信息在抽象方法getRegistration()
里由子类实现。当子类实现的getManagementRegistration()
接口有返回具体的注册信息并且配置的management信息后注册这个management信息 - 该类销毁的时候使用
ServiceRegistry
下线服务(下线过程跟注册过程雷同,下线getRegistration()
和getManagementRegistration()
方法里返回的注册信息),并调用
ServiceRegistry`的close方法关闭注册器。
总结一下,在SpringCloud体系下要实现新的服务注册、发现需要这6个步骤(最新版本的spring-cloud-commons已经建议我们直接使用Registration,废弃ServiceInstance):
- 实现ServiceRegistry接口,完成服务注册自身的具体逻辑
- 实现Registration接口,完成服务注册过程中获取注册信息的操作
- 继承AbstractAutoServiceRegistration,完成服务注册前后的逻辑
- 实现DiscoveryClient接口,完成服务发现的具体逻辑
- 实现ServiceInstance接口,在DiscoveryClient接口中被使用,完成服务注册组件与SpringCloud注册信息的转换
- 自动化配置类,将这些Bean进行构造
loadbalancer功能
客户端负载均衡功能。
一些接口的定义:
- ServiceInstanceChooser:服务实例选择器,使用load balancer根据serviceId获取具体的实例。
1 | public interface ServiceInstanceChooser { |
- LoadBalancerClient:负载均衡客户端,继承
ServiceInstanceChooser
。
1 | public interface LoadBalancerClient extends ServiceInstanceChooser { |
- RestTemplateCustomizer:RestTemplate的定制化器。
1 | public interface RestTemplateCustomizer { |
- LoadBalancerRequestTransformer:HttpRequest转换器,根据ServiceInstance转换成一个新的具有load balance功能的HttpRequest。
1 | (LoadBalancerRequestTransformer.DEFAULT_ORDER) |
- LoadBalancerRequest:函数式接口。对ServiceInstance操作并返回具体的泛型T。LoadBalancerRequestFactory的createRequest方法内部实现了该接口。实现过程中使用LoadBalancerRequestTransformer对request进行转换并返回了ClientHttpResponse。
1 | public interface LoadBalancerRequest<T> { |
@LoadBalanced
注解用于修饰RestTemplate,表示使用负载均衡客户端。
使用该注解修饰的RestTemplate会在LoadBalancerAutoConfiguration
自动化配置类中被处理:
1 | // 使用RestTemplateCustomizer定制化这些被@LoadBalanced注解修饰的RestTemplate |
LoadBalancerInterceptor
拦截器内部会对request请求进行拦截。拦截器内部使用LoadBalancerClient
完成请求的调用,这里调用的时候需要的LoadBalancerRequest
由LoadBalancerRequestFactory
构造,LoadBalancerRequestFactory
内部使用LoadBalancerRequestTransformer
对request进行转换。
hypermedia功能
springcloud对hateoas在服务发现领域上的支持。
关于hateoas可以参考一些资料:
https://github.com/spring-projects/spring-hateoas
https://spring.io/guides/gs/rest-hateoas/
其它注解、接口、类
@SpringCloudApplication注解
整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker这3个注解,说明@SpringCloudApplication注解表示一个分布式应用注解
ServiceInstance接口
表示服务发现系统里的一个服务实例
DefaultServiceInstance类
实现了ServiceInstance接口,是个默认的服务实例的实现
HostInfoEnvironmentPostProcessor类
属于EnvironmentPostProcessor。这个postprocessor会在Environment里加上当前vm的hostname和ip信息
CommonsClientAutoConfiguration类
自动化配置类。在该模块的 META-INF/spring.factories里配置,key为org.springframework.boot.autoconfigure.EnableAutoConfiguration。所以默认会被加载,内部会构造一些HealthIndicator,一些Endpoint
Spring Cloud Alibaba内部的spring-cloud-alibaba-nacos-discovery模块实现了spring-cloud-commons规范,提供了基于Nacos的服务发现,服务注册功能。Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。