[艾编程]SpringBoot启动过程浅析&服务架构演进

来自艾编程coding老师讲义,很散,很碎,有一定 SpringBoot 基础看会比较好。

1.SpringBoot 启动过程

还可以参考:Tomcat在SpringBoot中是如何启动的

启动类示例:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//程序的主入口
@SpringBootApplication  //Springboot应用
public class DemoApplication {

    public static void main(String[] args) {
        //开启了一个服务!
        SpringApplication.run(DemoApplication.class, args);
    }

}

applicationContext.xml < == > @Configuration
bean < == > @Bean
import < == > @Import

1.1 启动流程图

SpringApplication启动流程

1.2 自动装配过程核心调用链

@SpringBootApplication 
	--> @EnableAutoConfiguration 
		--> @AutoConfigurationImportSelector --> #selectImports --> #getAutoConfigurationEntry --> #getCandidateConfigurations
			--> SpringFactoriesLoader --> #loadFactoryNames --> #loadSpringFactories --> #FACTORIES_RESOURCE_LOCATION (META-INF/spring.factories)
		--> @AutoConfigurationPackage --> AutoConfigurationPackages.Registrar

其中AutoConfigurationImportSelector#getCandidateConfigurations方法很关键,会去读取META-INF/spring.factories

源码如下:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                                                                         getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}

1.3 SpringApplication.run()大致流程

  • 1.推断我们的应用是web应用还是 普通应用!
  • 2.加载初始化!
  • 3.设置监听器
  • 4.推断main方法,找到运行的主类

核心部分源码如下:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}

1.4 YAML 配置文件

Yet Another Markup Language强调这种语言以数据做为中心,而不是以标记语言为重点。

语法要点:冒号后空一格、下一层级可用两个空格作为缩进表示、同级别配置左侧需要对齐。。

简单示例:

字面量键值对:

k: value

对象,map

# 这句是注释
student:
  name: coding
  age: 3
 
student: {name: coding, age: 3}

数组(List,Set)

#语法
pets:
 - cat
 - dog
 - pig
 
pets: [cat,dog,pig]

1.5 @ConfigurationProperties

@ConfigurationProperties和 YAML 配置是黄金搭档。

SpringBoot自动配置底层基本全部都使用了这个注解。

@ConfigurationProperties VS @Value

特性对比@ConfigurationProperties@Value
功能批量从配置文件中注入属性一个个指定
松散绑定支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持!

在配置类中,通过注解@EnableConfigurationProperties即可自动装配@ConfigurationProperties注解标记的配置类。

可参考:DemoServiceProperties.javaDemoServiceAutoConfiguration.java

2.十五次架构演进

2.1 单体架构

架构演进-01
问题:用户量增大。

2.2 tomcat 和数据库分离

架构演进-02
问题:用户暴增,并发读写,瓶颈!

2.3 引入分布式缓存本地缓存

架构演进-03
问题:缓存一致性问题,缓存穿透、缓存雪崩.... 热点数据集中失效等。

2.4 负载均衡

架构演进-04
问题:单点登陆,session共享,文件上传下载!

2.5 数据库读写分离

架构演进-05
问题: 数据库同步,数据一致性问题!

2.6 数据库按照业务分库

架构演进-06

2.7 把大表拆分为一个个小表

架构演进-07
问题:大规模并发!

2.8 LVS,F5,多个nginx实现负载均衡

架构演进-08

2.9 通过DNS 实现机房的负载均衡

架构演进-09
机房级的水平扩展

2.10 引用NoSQL数据库,搜索引擎

架构演进-10

2.11 大应用拆分为小应用

架构演进-11

2.12 将公共模板抽象为微服务化

架构演进-12

2.13 引入服务总线

架构演进-13

2.14容器化

架构演进-14
Docker + k8s。

2.15 云平台系统

架构演进-15

Iaas: 基础设施即服务
Paas:平台即服务
Sass: 软件即服务

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×