# SpringBoot 自动装配原理

  1. @SpringBootApplication (main 方法上的注解)
  2. @EnableAutoConfiguration (自动装配核心注解)
  3. 导入 AutoConfigurationImportSelector 组件
  4. 通过 SpringFactoriesLoader 类读取
    • META-INF/spring.factories
    • org.springframework.boot.autoconfigure.AutoConfiguration.imports
  5. 条件注解进行过滤 (只有导入了相关 jar 包才会进行配置)
  6. ImportSelector 接口
  7. BeanDefinition
  8. 实例化 Bean 对象,放入 Spring 的 IOC 容器中

# 如何实现 Spring Boot Starter

  1. 写一个 starter 项目,一般是一个空壳,里面不写代码,主要起到 依赖其他项目的作用;
  2. 写一个真正实现自动装配逻辑的项目,在项目 classpath 下写一个 META-INF/spring.factories 文件;
  3. 在 spring.factories 中添加配置:org.springframework.boot.autoconfigure.EnableAutoConfigure = com.kablog.XXXConfiguration
  4. XXXConfiguration 类需要添加注解 @Configuration;
  5. 上述类一般使用 @Conditional 来适应不同的环境;
  6. 在 XXXConfiguration 类中编写具体代码实现自动化配置,给使用者把该配的配置好,让他人可以直接使用

# Spring Boot 与 SSM 有什么区别和优势

  • SSM10 随版本更新,依赖越来越多,配置越来越多,需要配置大量 xml 文件,开发繁琐
  • SpringBoot 约定优于配置,采用自动化配置,自动装配 Bean, 无需 SSM 一样的繁琐配置
  • SpringBoot 直接使用 java main 方法运行,可直接内嵌 Tomcat 服务器运行 SpringBoot 程序
  • SpingBoot 采用 starter 依赖简化 Maven 配置,自动管理所有 jar 包版本,加入 web starter, 自动引入内嵌的 Tomcat; 当然还提供了大量的 starter
  • SpringBoot 可以直接打包成 jar 包运行,部署简单

# Spring Boot 项目如何兼容老的 Spring 项目

  • 使用 @ImportResource 注解导入旧配置文件

# JavaConfig

  • @Configuration : 使用 @Configuration + 类 替代 xml 文件对 bean 定义
  • @Bean : 在 @Configuration 中 @Bean 替代 <bean id = "XX" class = "XX"></bean>
  • @ComponentScan : 使用 @ComponentScan(basePackage="XX") + 类 替代 <context:componentscan basepackage = "XX"> \
  • @EnableWebMvc : 使用 EnableWebMvc 替代 <mvc:annotation-driven>
  • @ImportResource : 使用 @ImportResource(locations = "classpath:xxx.xml") + 类 替代 <import resource = "xxx.xml">
  • @Properties : 使用 @Properties("classpath:*.properties") + 类 替代 <context:property-placeholder location="classpath:*.properties">
  • @Value : 使用 @Value("${jdbc.xxx}") 来配置数据源

使用注解来开发项目

# 如何排除某些类的自动装配

某些时候配置了如 mybatis-starter 等依赖包,它会自动装配。此时若没有在 properties 中填入相应的 host/port/password/url 等内容,那么运行就会报错。此时应先排除自动装配

  • properties 文件中添加 spring.autoconfigure.exclude = org.xxx.DataSourceAutoConfiguration

  • 在类上添加注解 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,xxx.class})

# 如何实现异步调用

# 是什么

asynchronous call (异步调用): 一个无需等待被调用函数的返回值就能让操作继续进行的方法;

# 使用场景

  • 对于一些不需要在主线流程中执行的任务:如注册时发送欢迎短信
  • 不需要实施等待计算结果的任务:如业务执行记录日志
  • 为了利用多核 cpu 并发执行的任务:如下单时获取用户住址,用户余额,商品信息

# 怎么解决

将这些任务异步执行,即放在另一个线程中去执行,从而避免主线程的阻塞和等待

  • 方式一:@EnableAsync + @Async + Future + ThreadPoolTaskExecutor
  • 方式二:CompletableFuture + ThreadPoolTaskExecutor

# SpringBoot 默认使用什么动态代理

默认使用 CGLIB 动态代理而不是 JDK 动态代理

主要是考虑兼容性

CGLIB 动态代理可以代理任何类型的目标类,而 JDK 动态代理只能代理实现了接口的目标类,

因此 CGLIB 覆盖了 JDK 所有使用场景,故为了保证 SpringBoot 中的 AOP 可以面向任何类型的 Bean,

SpringBoot 默认使用 CGLIB 作为代理的实现方式.

# SpringCloud 组件

  • 注册中心:Eureka,Nacos,Zookeeper,Consul;(服务注册)
  • 负载均衡:Ribbon,LoadBalancer;(客户端的负载均衡)
  • 服务调用:Feign,OpenFeign,Dubbo RPC;(优雅调用远程服务)
  • 配置中心:Spring Cloud Config,Nacos;(统一管理服务配置)
  • 熔断降级:Hystrix,Sentinel;(急骤请求,防止服务雪崩)
  • 分布式事务:Seata;(跨库跨服务的事务管理)
  • 服务网关:Zuul 1.x,Zuul 2.x,Spring Cloud Gateway;(系统入口门面)
  • 链路跟踪:Skywalking,Zipkin;(监控服务状态,协助排查问题)

# Spring Cloud 的理解

  1. 将微服务面临的负载均衡,服务的注册与发现,服务调用,服务路由,服务熔断等技术问题解决方案打包好.
  2. 提供了一整套微服务解决方案,降低开发难度,提供统一标准
  3. 为 Spring 生态注入更强的生命力

# 服务熔断?服务降级?

  • 服务熔断:当服务 A 调用服务 B 时,如果此时服务 B 不可用,那么上游的服务 A 为了保证自己不受影响,就切断调用服务 B, 防止发生服务雪崩,直到 B 服务恢复.(具体指提前做好一种兜底措施,比如返回假的数据,或者记录数据信息到数据库,redis, 文件中,后续进行补救,直到 B 服务恢复)

  • 服务降级:当系统负载过高时,对非核心的业务服务进行关闭,来保证核心业务的正常运行;(关闭某些不重要的服务,或者拒绝低优先级应用的服务请求,保证核心应用正常工作)

  • 相同:目的相同:保证服务可用性,防止系统整体负载过大甚至崩溃;

    ​ 表现相同:都是表现出服务暂时不可用的状态

  • 不同:服务熔断一般是某个服务 (下游服务) 故障引起,而服务降级一般是从整体负荷考虑.

# 项目重构时为何要对系统进行拆分

# Eureka 和 Nacos 区别

  • 相同:1. 都用于服务的注册与发现 2. 都支持服务的心跳健康检查 3. 都支持高可用

  • 不同:

    NacosEureka
    支持主动对微服务状态检测,临时实例心跳检测,永久实例主动检测
    临时实例不正常会从注册中心删除,永久实例不会删除
    支持服务列表变更时的主动消息推送,服务列表更新会更及时
    集群支持两种模式,默认 AP, 存在非临时实例时采用 CP 模式只支持 AP
    支持注册中心,配置中心只支持注册中心
    具备较好上下线流量管理界面后台界面仅供展示,需使用 API 操作上下线,无流量管理
    社区活跃闭源

# ACID,BASE 理论,CAP 理论的关系

# ACID

ACID 是传统数据库中常用的设计理念

  1. Atomicity (原子性)
  2. Consistency (一致性)
  3. Isolation (隔离性)
  4. Durability (持久性)

ACID 它追求的是数据的强一致性模型

# BASE 理论

BASE 理论支持的是大型分布式系统;

  1. 基本可用 (Basically Available): 分布式系统出现不可预知故障时,允许损失部分可用性
  2. 软状态 (Soft State): 允许系统中的数据存在中间状态,允许系统在不同节点的数据副本之间同步存在延时
  3. 最终一致性 (Eventually Consistent): 所有数据副本在一段时间同步后最终一致的状态,无需实时保证系统数据强一致

BASE 理论是通过牺牲强一致性以获得高可用性

# CAP 理论

CAP 理论是支持分布式系统而提出的;

  1. C: 一致性 (Consistency)
  2. A: 可用性 (Availability)
  3. P: 分区容错性 (Tolerance of network Partition)

分布式系统无法做到 CAP, 只能做到其中两项,要么 CP, 要么 AP

# 三者关系

ACID 和 CAP,BASE 代表了两种截然相反的设计哲学;

在分布式系统设计中,根据不同场景的实际情况,可以把 ACID,CAP,BASE 结合起来使用

# 注册中心选择 CP 还是 AP

简单来说,应该优先选择 AP (可用性) 然后保证最终一致性即可,而选择 CP (一致性) 的话,随着应用规模增大,应用实例频繁注册或删除,必将影响注册中心服务注册与发现的效率.

# 接口幂等性

幂等性 = 多次执行无副作用

考虑幂等性即考虑多次执行,多次请求的情况

在以下场景可能会使用到

  • 因网络波动引起的重复请求
  • 用户重复操作 (无意触发或因无响应而有意触发等)
  • 应用使用了失败或超时重试机制 (如 RPC 重试,业务层重试等)
  • 第三方平台的接口 (如:支付成功回调接口), 因为异常导致多次回调
  • 中间件 / 应用服务根据自身特性,也有可能进行重试
  • 用户双击提交按钮
  • 用户页面重复刷新
  • 使用浏览器后退按钮重复之前的操作,导致重复提交表单
  • 使用浏览器历史记录重复提交表单
  • 浏览器重复的 http 请求
  • 定时任务重复执行

一般在数据访问层进行幂等性的设计

使用唯一索引防止幂等性问题:简单粗暴,当数据重复时会抛出异常,保证不会出现脏数据

使用 Token+Redis 的幂等方案 (申请 token 阶段和业务操作阶段): 先获得 token 存入 redis, 根据 token 执行处理,然后删除 token. 重复请求时,由于缓存中没有 token, 表示非法请求

# 分布式事务

事务通常用于数据库领域

事务是指对数据库进行读或写的一组操作,要么都执行,要么都不执行,不允许只执行一部分的情况;

由 insert,delete,update,select 组成的一组操作,要么都 commit, 要么都 rollback

本地事务:仅支持单库事务,保证 ACID

分布式事务:多个库,因此有多个数据源的连接,不能使用 spring 的事务管理

分布式事务解决方案

  • 2PC
  • 3PC
  • TCC
  • 本地消息异步确认
  • 可靠消息最终一致性
  • 最大努力通知
  • RocketMQ 解决分布式事务
  • 阿里巴巴的 Seata 解决分布式事务

如何进行服务的限流

  • 计数器法
  • 漏桶算法
  • 令牌桶算法 (Guava 框架)

分布式环境如何进行服务的限流

  • Nginx 限流
  • OpenResty 限流
  • Sentinel 限流
  • Redis + Lua 限流
  • Spring Cloud Gateway 限流
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

KagurazakaAsahi 微信支付

微信支付