(一)Spring-Cloud源码分析之核心流程关系及springcloud与springboot包区别(新)

1. 前言

在2022年3月份,当时对Springcloud做了很简单的分析,在2023年看来当初那篇文章分析的太过表面,讲述的内容也不是很全面,因此在这里重新做一次回顾,新增修改一些文章内容。

2. springcloud简介

Springcloud在Springboot的基础上新增了对分布式框架的支持,如下:

  • 服务发现注册:Eureka、Zookeeper的starter包;
  • 配置中心:Springcloud Config,平替为流行的Nacos和Apollo;
  • 熔断降级和限流:官方的Hystrix和阿里的Sentinel;
  • 负载均衡:Ribbon+Feign组合;
  • 服务网关:Springcloud Gateway或Zuul

Springcloud需要依赖于Springboot,因此想要玩转Springcloud,前提是对Springboot很熟悉,否则很容易对功能边界模糊不清。

3. Springcloud包简介

Springcloud的依赖管理包这次选用的是Greenwich.SR2,依赖如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Greenwich.SR3</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

依赖中主要有Springcloud的通用包:

  • spring-cloud-commons:制定微服务中的服务注册、发现、负载均衡和熔断器等功能的抽象层代码;
  • spring-cloud-context:引入spring-cloud的上下文及接入springboot的一系列插件,用以支持bootstrap文件的读取、上下文刷新等机制的引入;
  • spring-cloud-loadbalancer:负载均衡相关功能。

除了上面三个通用包外,还支持Springcloud其它体系的依赖:

spring-cloud-netflix
spring-cloud-stream
spring-cloud-task
spring-cloud-config
spring-cloud-function
spring-cloud-gateway
spring-cloud-consul
spring-cloud-sleuth
spring-cloud-vault
spring-cloud-zookeeper
spring-cloud-security
spring-cloud-cloudfoundry
spring-cloud-bus
spring-cloud-contract
spring-cloud-aws
spring-cloud-openfeign
spring-cloud-kubernetes
spring-cloud-gcp

这些就不一一介绍了,都是一些Springcloud官方支持的依赖包,如对应功能的starter、core等包。

4. Springcloud和Springboot流程关系

在Springcloudspring-cloud-context包中的spring.factories文件中有ApplicationListener=BootstrapApplicationListener,Springcloud就是以这个类为入口开启了Springcloud的启动流程。如下图:

Springcloud和Springboot流程关系图

当Springboot完成创建Environment对象后会发布ApplicationEnvironmentPreparedEvent事件,BootstrapApplicationListener便是监听该事件启动Springcloud的启动流程。

从上图也能看出来Springboot和Springcloud的核心启动流程基本一致,且Springcloud大量复用了Springboot放开的接口来实现支持微服务框架。在Springcloud中会存在两个ApplicationContext,两者为父子关系,Springcloud的ApplicationContext为父,Springboot的ApplicationContext为子。

所以从整体上来看,Springcloud是以Springboot放开的ApplicationListener接口为起点,在Springboot的基础上再搭建了一个父ApplicationContext,以这样的结构去扩展Cloud相关框架,并不影响原Springboot的流程。

5. Springcloud启动流程新增的功能和接口

5.1 新增接口

Springcloud在原来Springboot的基础上新增了BootstrapConfigurationSPI机制接口,在BootstrapApplicationListener类中完成加载,并在Springcloud的ApplicationContext刷新流程中完成Import解析。

在spring.factories文件中配置如下:

# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
  1. PropertySourceBootstrapConfiguration:用于配置使用PropertySourceLocator接口的实现类,其作用便是根据Environment对象生成PropertySource对象,并最终保存在bootstrapProperties属性对象中;
  2. EncryptionBootstrapConfiguration:用于配置对Environment对象中的属性进行加解密;
  3. ConfigurationPropertiesRebinderAutoConfiguration:自动注入类,在前面的EnableAutoConfiguration配置项中已经有了,这里重新配置了一下,个人猜测的目的是用于重新绑定spring-cloud上下文,毕竟EnableAutoConfiguration中的配置是针对springboot上下文的;
  4. PropertyPlaceholderAutoConfiguration:引入PropertySourcesPlaceholderConfigurer类,保证springcloud上下文可以使用通配符去替换值。

5.2 新增功能类

5.2.1 spring-cloud-context包

EnableAutoConfiguration自动注入类:

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
  1. ConfigurationPropertiesRebinderAutoConfiguration:用于自动装填springcloud的重绑定类,用于在springcloud上下文刷新时重新绑定各个bean对象和属性;
  2. LifecycleMvcEndpointAutoConfiguration:用于自动注入EnvironmentManager类;
  3. RefreshAutoConfiguration:自动注入springcloud上下文刷新类,springcloud的RefreshScope和RefreshEventListener等刷新组建便是在这里面被注入的;
  4. RefreshEndpointAutoConfiguration:用于注入刷新Endpoint切点的自动刷新注入类;
  5. WritableEnvironmentEndpointAutoConfiguration:用于自动注入WritableEnvironmentEndpoint类。

ApplicationListener程序监听器类:

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\
org.springframework.cloud.context.restart.RestartListener
  1. BootstrapApplicationListener:用于引入springcloud上下文和springcloud自定义配置类,同时也负责生成springcloud上下文对象,并将其设置为springboot的父上下文,也可以通过属性配置这个类不进行加载;
  2. LoggingSystemShutdownListener:负责清空前面设置过的Log日志信息,以避免后续的日志加载收到前面日志配置的影响;
  3. RestartListener:保存spring的上下文,以便后续在有必要的时候重启上下文。

5.2.2 spring-cloud-commons包

EnableAutoConfiguration自动注入类:

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.CommonsClientAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.httpclient.HttpClientConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.configuration.CompatibilityVerifierAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration

可以看到相对于spring-cloud-context而言自动注入类的配置项是非常多的,而且从名字也可以看出来这是用来进行服务注册、发现及负载均衡相关的。大致作用:

  1. CommonsClientAutoConfiguration:用来自动注册通用的客户端组件,如健康检查及Endpoint切点的组件对象;
  2. CompositeDiscoveryClientAutoConfiguration:注册用来保存多种DiscoveryClient对象类型的对象CompositeDiscoveryClient;
  3. NoopDiscoveryClientAutoConfiguration:注册一个实现了DiscoveryClient接口,用来代表基础机器信息NoopDiscoveryClient类型对象;
  4. SimpleDiscoveryClientAutoConfiguration:注册SimpleDiscoveryProperties对象及相关的其它对象,在前面注册过的NoopDiscoveryClient基础上新增SimpleDiscoveryClient类型的对象;
  5. CloudHypermediaAutoConfiguration:注册用来管理和刷新远程资源的相关对象;
  6. AsyncLoadBalancerAutoConfiguration:注册Ribbon相关的异步负载均衡相关配置类;
  7. LoadBalancerAutoConfiguration:注册Ribbon相关的同步负载均衡和重试机制相关配置类;
  8. ReactorLoadBalancerClientAutoConfiguration:用来注册@LoadBalanced注解及ReactiveLoadBalancer等负载均衡类;
  9. ReactiveLoadBalancerAutoConfiguration:为Reactor自动注入类的辅助类;
  10. ServiceRegistryAutoConfiguration:自动注入服务注册切点相关类;
  11. HttpClientConfiguration:自动注入http相关的实现类,支持okhttp和apache;
  12. UtilAutoConfiguration:注册提供通用方法的类,如InetUtilsProperties和InetUtils;
  13. CompatibilityVerifierAutoConfiguration:自动注入系统的校验类,如校验springboot版本和springcloud版本是否兼容的SpringBootVersionVerifier,以及可以保存其它校验类的可组合式CompositeCompatibilityVerifier;
  14. AutoServiceRegistrationAutoConfiguration:自动发现服务注入类,用来校验自动注入相关功能是否正常执行,如果没有则抛异常。

上面十四个都是大概的描述了其中的功能,里面用到了很多的@Autowired注解,因此如果程序后续注入了相关的实现类都会被注入,这也是为何把这个包称为springcloud微服务注册发现的抽象层,因为后续只要有相关的实现接入,便可以自动装填运行,方式比较新颖。

EnvironmentPostProcessor环境对象后处理器:

spring.factories文件中对于EnvironmentPostProcessor选项只有一个实现配置类:

  • HostInfoEnvironmentPostProcessor:用来在环境对象中生成springCloudClientHostInfo属性信息,这里面包括了本机器的IP地址和主机名称信息,用来提供机器的身份证明。

FailureAnalyzer启动错误分析类:

spring.factories对于FailureAnalyzer也只有一个实现配置类:

  • CompatibilityNotMetFailureAnalyzer:用来组织程序发生错误时的输出内容。

6. Springcloud实现机制带来的问题

Springcloud由于是在原Springboot的基础上新建了一个父ApplicationContext,因此SPI机制上会进行重复读取,导致父子两个ApplicationContext都含有一模一样的SPI实现类,SPI实现类就会执行两次。

7. Springcloud和Springboot简单的性能差异对比

差异对比springboot依赖如下:

<parent>
    <!-- springboot的核心包 -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
</parent>

<dependencies>
    <!-- springboot的web启动包 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>

差异对比springcloud依赖如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>

项目只有一个controller,单纯的启动springboot和springcloud时间统计表(非严谨):

次数springbootspringcloud
11.139 seconds (JVM running for 1.615)1.695 seconds (JVM running for 2.188)
21.145 seconds (JVM running for 1.63)1.714 seconds (JVM running for 2.221)
31.42 seconds (JVM running for 1.942)1.76 seconds (JVM running for 2.255)
41.135 seconds (JVM running for 1.623)1.74 seconds (JVM running for 2.24)
51.133 seconds (JVM running for 1.626)1.694 seconds (JVM running for 2.308)
61.164 seconds (JVM running for 1.658)1.708 seconds (JVM running for 2.218)
71.214 seconds (JVM running for 1.723)1.715 seconds (JVM running for 2.212)
81.164 seconds (JVM running for 1.658)1.743 seconds (JVM running for 2.259)
91.142 seconds (JVM running for 1.636)1.756 seconds (JVM running for 2.261)
101.126 seconds (JVM running for 1.595)1.701 seconds (JVM running for 2.194)

去掉最高和最低值后平均启动速度如下:

  • springboot:平均启动时间为1.1545s
  • springcloud:平均启动时间为1.7215

springcloud启动时间较springboot时间平均多出0.567s,即567ms,再加上多引入了包,导致JVM启动时间会延长半秒左右,因此使用springcloud会导致整个项目启动时间延迟1s左右,但这个性能消耗完全是可以忽略不计的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值